private Dictionary <string, Mesh> GenerateMeshes(float height, float margin = 0f) { var meshes = new Dictionary <string, Mesh>(); var fullMatrix = new Matrix3D(); fullMatrix.RotateZMatrix(MathF.DegToRad(180.0f)); var baseRadius = _data.BaseRadius - _data.RubberThickness + margin; var endRadius = _data.EndRadius - _data.RubberThickness + margin; // calc angle needed to fix P0 location var sinAngle = (baseRadius - endRadius) / _data.FlipperRadius; if (sinAngle > 1.0) { sinAngle = 1.0f; } if (sinAngle < -1.0) { sinAngle = -1.0f; } var fixAngle = MathF.Asin(sinAngle); var fixAngleScale = fixAngle / (float)(System.Math.PI * 0.5); // scale (in relation to 90 deg.) // fixAngleScale = 0.0; // note: if you force fixAngleScale = 0.0 then all will look as old version // lambda used to apply fix void ApplyFix(ref Vertex3DNoTex2 vert, Vertex2D center, float midAngle, float radius, Vertex2D newCenter) { var vAngle = MathF.Atan2(vert.Y - center.Y, vert.X - center.X); var nAngle = MathF.Atan2(vert.Ny, vert.Nx); // we want have angles with same sign as midAngle, fix it: if (midAngle < 0.0) { if (vAngle > 0.0) { vAngle -= (float)(System.Math.PI * 2.0); } if (nAngle > 0.0) { nAngle -= (float)(System.Math.PI * 2.0); } } else { if (vAngle < 0.0) { vAngle += (float)(System.Math.PI * 2.0); } if (nAngle < 0.0) { nAngle += (float)(System.Math.PI * 2.0); } } nAngle -= (vAngle - midAngle) * fixAngleScale * MathF.Sign(midAngle); vAngle -= (vAngle - midAngle) * fixAngleScale * MathF.Sign(midAngle); float nL = new Vertex2D(vert.Nx, vert.Ny).Length(); vert.X = MathF.Cos(vAngle) * radius + newCenter.X; vert.Y = MathF.Sin(vAngle) * radius + newCenter.Y; vert.Nx = MathF.Cos(nAngle) * nL; vert.Ny = MathF.Sin(nAngle) * nL; } // base and tip var baseMesh = new Mesh(Base, Vertices, Indices).Clone(); for (var t = 0; t < 13; t++) { for (var i = 0; i < baseMesh.Vertices.Length; i++) { var v = baseMesh.Vertices[i]; if (v.X == VertsBaseBottom[t].X && v.Y == VertsBaseBottom[t].Y && v.Z == VertsBaseBottom[t].Z) { ApplyFix(ref baseMesh.Vertices[i], new Vertex2D(VertsBaseBottom[6].X, VertsBaseBottom[0].Y), (float)-(System.Math.PI * 0.5), baseRadius, new Vertex2D(0, 0)); } if (v.X == VertsTipBottom[t].X && v.Y == VertsTipBottom[t].Y && v.Z == VertsTipBottom[t].Z) { ApplyFix(ref baseMesh.Vertices[i], new Vertex2D(VertsTipBottom[6].X, VertsTipBottom[0].Y), (float)(System.Math.PI * 0.5), endRadius, new Vertex2D(0, _data.FlipperRadius)); } if (v.X == VertsBaseTop[t].X && v.Y == VertsBaseTop[t].Y && v.Z == VertsBaseTop[t].Z) { ApplyFix(ref baseMesh.Vertices[i], new Vertex2D(VertsBaseBottom[6].X, VertsBaseBottom[0].Y), (float)(-System.Math.PI * 0.5), baseRadius, new Vertex2D(0, 0)); } if (v.X == VertsTipTop[t].X && v.Y == VertsTipTop[t].Y && v.Z == VertsTipTop[t].Z) { ApplyFix(ref baseMesh.Vertices[i], new Vertex2D(VertsTipBottom[6].X, VertsTipBottom[0].Y), (float)(System.Math.PI * 0.5), endRadius, new Vertex2D(0, _data.FlipperRadius)); } } } baseMesh.Transform(fullMatrix, null, z => z * _data.Height + height); meshes[Base] = baseMesh; // rubber var rubberMesh = new Mesh(Rubber, Vertices, Indices).Clone(); for (var t = 0; t < 13; t++) { for (var i = 0; i < rubberMesh.Vertices.Length; i++) { var v = rubberMesh.Vertices[i]; if (v.X == VertsBaseBottom[t].X && v.Y == VertsBaseBottom[t].Y && v.Z == VertsBaseBottom[t].Z) { ApplyFix(ref rubberMesh.Vertices[i], new Vertex2D(VertsBaseBottom[6].X, VertsBaseBottom[0].Y), (float)(-System.Math.PI * 0.5), baseRadius + _data.RubberThickness + margin, new Vertex2D(0, 0)); } if (v.X == VertsTipBottom[t].X && v.Y == VertsTipBottom[t].Y && v.Z == VertsTipBottom[t].Z) { ApplyFix(ref rubberMesh.Vertices[i], new Vertex2D(VertsTipBottom[6].X, VertsTipBottom[0].Y), (float)(System.Math.PI * 0.5), endRadius + _data.RubberThickness + margin, new Vertex2D(0, _data.FlipperRadius)); } if (v.X == VertsBaseTop[t].X && v.Y == VertsBaseTop[t].Y && v.Z == VertsBaseTop[t].Z) { ApplyFix(ref rubberMesh.Vertices[i], new Vertex2D(VertsBaseBottom[6].X, VertsBaseBottom[0].Y), (float)(-System.Math.PI * 0.5), baseRadius + _data.RubberThickness + margin, new Vertex2D(0, 0)); } if (v.X == VertsTipTop[t].X && v.Y == VertsTipTop[t].Y && v.Z == VertsTipTop[t].Z) { ApplyFix(ref rubberMesh.Vertices[i], new Vertex2D(VertsTipBottom[6].X, VertsTipBottom[0].Y), (float)(System.Math.PI * 0.5), endRadius + _data.RubberThickness + margin, new Vertex2D(0, _data.FlipperRadius)); } } } rubberMesh.Transform(fullMatrix, null, z => z * _data.RubberWidth + (height + _data.RubberHeight + margin * 10f)); meshes[Rubber] = rubberMesh; return(meshes); }