private Dictionary <string, Mesh> GetMeshes(Table.Table table, Origin origin) { var lightMesh = Bulb.Clone(); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); var transX = origin == Origin.Global ? _data.Center.X : 0f; var transY = origin == Origin.Global ? _data.Center.Y : 0f; var transZ = origin == Origin.Global ? height : 0f; foreach (var vertex in lightMesh.Vertices) { vertex.X = vertex.X * _data.MeshRadius + transX; vertex.Y = vertex.Y * _data.MeshRadius + transY; vertex.Z = vertex.Z * _data.MeshRadius * table.GetScaleZ() + transZ; } var socketMesh = Socket.Clone(); foreach (var vertex in socketMesh.Vertices) { vertex.X = vertex.X * _data.MeshRadius + transX; vertex.Y = vertex.Y * _data.MeshRadius + transY; vertex.Z = vertex.Z * _data.MeshRadius * table.GetScaleZ() + transZ; } return(new Dictionary <string, Mesh> { { "Bulb", lightMesh }, { "Socket", socketMesh }, }); }
protected override Tuple <Matrix3D, Matrix3D> GetTransformationMatrix(Table.Table table) { var fullMatrix = new Matrix3D(); var tempMat = new Matrix3D(); fullMatrix.RotateZMatrix(RotationZ); tempMat.RotateYMatrix(MathF.DegToRad(_data.RotY)); fullMatrix.Multiply(tempMat); tempMat.RotateXMatrix(MathF.DegToRad(_data.RotX)); fullMatrix.Multiply(tempMat); var vertMatrix = new Matrix3D(); tempMat.SetTranslation(-Position.X, -Position.Y, -Position.Z); vertMatrix.Multiply(tempMat, fullMatrix); tempMat.SetScaling(Scale.X, Scale.Y, Scale.Z * table.GetScaleZ()); vertMatrix.Multiply(tempMat); if (_data.Height == _data.HitHeight) { // do not z-scale the hit mesh tempMat.SetTranslation(Position.X, Position.Y, _data.Height + table.TableHeight); } else { tempMat.SetTranslation(Position.X, Position.Y, _data.Height * table.GetScaleZ() + table.TableHeight); } vertMatrix.Multiply(tempMat); return(new Tuple <Matrix3D, Matrix3D>(vertMatrix, fullMatrix)); }
private Mesh GetMesh(string id, Table.Table table, Origin origin) { if (_data.Center == null) { throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); } var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); switch (id) { case Base: { var mesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); return(TranslateMesh(mesh, z => z * table.GetScaleZ() + height, origin)); } case Cap: { var mesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); return(TranslateMesh(mesh, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin)); } case Ring: { var mesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); return(TranslateMesh(mesh, z => z * table.GetScaleZ() + height, origin)); } case Skirt: { var mesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); return(TranslateMesh(mesh, z => z * table.GetScaleZ() + (height + 5.0f), origin)); } } throw new ArgumentException("Unknown bumper mesh \"" + id + "\"."); }
private Dictionary <string, Mesh> GetMeshes(Table.Table table, Origin origin) { if (_data.Center == null) { throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); } var matrix = new Matrix3D().RotateZMatrix(MathF.DegToRad(_data.Orientation)); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); return(new Dictionary <string, Mesh> { { "Base", GenerateMesh(_scaledBaseMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, { "Ring", GenerateMesh(_scaledRingMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, { "Skirt", GenerateMesh(_scaledSocketMesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin) }, { "Cap", GenerateMesh(_scaledCapMesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin) } }); }
public void Init(Table.Table table) { var stroke = _data.Stroke; _beginY = _data.Center.Y; _endY = _data.Center.Y - stroke; NumFrames = (int)(stroke * (float)(PlungerFrameCount / 80.0)) + 1; // 25 frames per 80 units travel _invScale = NumFrames > 1 ? 1.0f / (NumFrames - 1) : 0.0f; _dyPerFrame = (_endY - _beginY) * _invScale; _circlePoints = _data.Type == PlungerType.PlungerTypeFlat ? 0 : 24; _springLoops = 0.0f; _springEndLoops = 0.0f; _springGauge = 0.0f; _springRadius = 0.0f; _springMinSpacing = 2.2f; _rodY = _beginY + _data.Height; // note the number of cells in the source image _srcCells = _data.AnimFrames; if (_srcCells < 1) { _srcCells = 1; } // figure the width in relative units (0..1) of each cell _cellWid = 1.0f / _srcCells; if (table != null) { _zHeight = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) + _data.ZAdjust; _zScale = table.GetScaleZ(); } _desc = GetPlungerDesc(); }
private Dictionary <string, Mesh> GetMeshes(Table.Table table, Origin origin) { if (_data.Center == null) { throw new InvalidOperationException($"Cannot export bumper {_data.Name} without center."); } var matrix = Matrix3D.Identity; var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); if (_generatedScale != _data.Radius) { _scaledBaseMesh = BaseMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); _scaledCapMesh = CapMesh.Clone().MakeScale(_data.Radius * 2, _data.Radius * 2, _data.HeightScale); _scaledRingMesh = RingMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); _scaledSocketMesh = SocketMesh.Clone().MakeScale(_data.Radius, _data.Radius, _data.HeightScale); } return(new Dictionary <string, Mesh> { { "Base", GenerateMesh(_scaledBaseMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, { "Ring", GenerateMesh(_scaledRingMesh, matrix, z => z * table.GetScaleZ() + height, origin) }, { "Skirt", GenerateMesh(_scaledSocketMesh, matrix, z => z * table.GetScaleZ() + (height + 5.0f), origin) }, { "Cap", GenerateMesh(_scaledCapMesh, matrix, z => (z + _data.HeightScale) * table.GetScaleZ() + height, origin) } }); }
private Mesh GetSocketMesh(Table.Table table, Origin origin) { var socketMesh = SocketMesh.Clone(); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); var transX = origin == Origin.Global ? _data.Center.X : 0f; var transY = origin == Origin.Global ? _data.Center.Y : 0f; var transZ = origin == Origin.Global ? height : 0f; foreach (var vertex in socketMesh.Vertices) { vertex.X = vertex.X * _data.MeshRadius + transX; vertex.Y = vertex.Y * _data.MeshRadius + transY; vertex.Z = vertex.Z * _data.MeshRadius * table.GetScaleZ() + transZ; } return socketMesh; }
private Mesh GetBulbMesh(Table.Table table, Origin origin) { var bulbMesh = BulbMesh.Clone(); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ(); var transX = origin == Origin.Global ? _data.Center.X : 0f; var transY = origin == Origin.Global ? _data.Center.Y : 0f; var transZ = origin == Origin.Global ? height : 0f; for (var i = 0; i < bulbMesh.Vertices.Length; i++) { bulbMesh.Vertices[i].X = bulbMesh.Vertices[i].X * _data.MeshRadius + transX; bulbMesh.Vertices[i].Y = bulbMesh.Vertices[i].Y * _data.MeshRadius + transY; bulbMesh.Vertices[i].Z = bulbMesh.Vertices[i].Z * _data.MeshRadius * table.GetScaleZ() + transZ; } return(bulbMesh); }
public Matrix3D GetPostMatrix(Table.Table table, Origin origin) { switch (origin) { case Origin.Original: return new Matrix3D().SetTranslation( _data.Center.X, _data.Center.Y, table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y) * table.GetScaleZ() ); case Origin.Global: return Matrix3D.Identity; default: throw new ArgumentOutOfRangeException(nameof(origin), origin, "Unknown origin " + origin); } }
public KickerHit(KickerData data, float radius, float height, Table.Table table) : base(data.Center.Clone(), radius, height, height + data.HitHeight, ItemType.Kicker) { HitMesh = new Vertex3D[KickerHitMesh.Vertices.Length]; if (!data.LegacyMode) { var rad = Radius * 0.8f; for (var t = 0; t < KickerHitMesh.Vertices.Length; t++) { // find the right normal by calculating the distance from current ball position to vertex of the kicker mesh var vPos = new Vertex3D(KickerHitMesh.Vertices[t].X, KickerHitMesh.Vertices[t].Y, KickerHitMesh.Vertices[t].Z); vPos.X = vPos.X * rad + data.Center.X; vPos.Y = vPos.Y * rad + data.Center.Y; vPos.Z = vPos.Z * rad * table.GetScaleZ() + height; HitMesh[t] = vPos; } } IsEnabled = data.IsEnabled; }
protected override Tuple <Matrix3D, Matrix3D> GetTransformationMatrix(Table.Table table) { // scale matrix var scaleMatrix = new Matrix3D(); scaleMatrix.SetScaling(Scale.X, Scale.Y, Scale.Z); // translation matrix var transMatrix = new Matrix3D(); transMatrix.SetTranslation(Position.X, Position.Y, Position.Z + table.TableHeight); // translation + rotation matrix var rotTransMatrix = new Matrix3D(); rotTransMatrix.SetTranslation(_data.RotAndTra[3], _data.RotAndTra[4], _data.RotAndTra[5]); var tempMatrix = new Matrix3D(); tempMatrix.RotateZMatrix(MathF.DegToRad(_data.RotAndTra[2])); rotTransMatrix.Multiply(tempMatrix); tempMatrix.RotateYMatrix(MathF.DegToRad(_data.RotAndTra[1])); rotTransMatrix.Multiply(tempMatrix); tempMatrix.RotateXMatrix(MathF.DegToRad(_data.RotAndTra[0])); rotTransMatrix.Multiply(tempMatrix); tempMatrix.RotateZMatrix(MathF.DegToRad(_data.RotAndTra[8])); rotTransMatrix.Multiply(tempMatrix); tempMatrix.RotateYMatrix(MathF.DegToRad(_data.RotAndTra[7])); rotTransMatrix.Multiply(tempMatrix); tempMatrix.RotateXMatrix(MathF.DegToRad(_data.RotAndTra[6])); rotTransMatrix.Multiply(tempMatrix); var fullMatrix = scaleMatrix.Clone(); fullMatrix.Multiply(rotTransMatrix); fullMatrix.Multiply(transMatrix); // fullMatrix = Smatrix * RTmatrix * Tmatrix scaleMatrix.SetScaling(1.0f, 1.0f, table.GetScaleZ()); fullMatrix.Multiply(scaleMatrix); return(new Tuple <Matrix3D, Matrix3D>(fullMatrix, null)); }
public void Init(Table.Table table) { var height = table.GetSurfaceHeight(Data.Surface, Data.Center.X, Data.Center.Y) * table.GetScaleZ(); // reduce the hit circle radius because only the inner circle of the kicker should start a hit event var radius = Data.Radius * (Data.LegacyMode ? Data.FallThrough ? 0.75f : 0.6f : 1f); _hit = new KickerHit(Data, radius, height, table, this); // height of kicker hit cylinder }
private Mesh GenerateTopMesh(Table.Table table) { var topMesh = new Mesh("Top"); var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints); var numVertices = vVertex.Length; var rgNormal = new Vertex2D[numVertices]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var dx = pv1.X - pv2.X; var dy = pv1.Y - pv2.Y; if (dx != 0.0f || dy != 0.0f) { var invLen = 1.0f / MathF.Sqrt(dx * dx + dy * dy); rgNormal[i] = new Vertex2D { X = dy * invLen, Y = dx * invLen }; } else { rgNormal[i] = new Vertex2D { X = 0.0f, Y = 0.0f }; } } // draw top var vPoly = new List <int>(new int[numVertices]); for (var i = 0; i < numVertices; i++) { vPoly[i] = i; } topMesh.Indices = Mesh.PolygonToTriangles(vVertex, vPoly); var numPolys = topMesh.Indices.Length / 3; if (numPolys == 0) { // no polys to render leave vertex buffer undefined return(null); } var heightNotDropped = _data.HeightTop * table.GetScaleZ(); var heightDropped = _data.HeightBottom * table.GetScaleZ() + 0.1; var invTableWidth = 1.0f / table.Width; var invTableHeight = 1.0f / table.Height; Vertex3DNoTex2[][] vertsTop = { new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices] }; for (var i = 0; i < numVertices; i++) { var pv0 = vVertex[i]; vertsTop[0][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = heightNotDropped + table.TableHeight, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[1][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = (float)heightDropped, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[2][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = _data.HeightBottom, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = -1.0f }; } topMesh.Vertices = vertsTop[0]; return(topMesh); }
private Mesh GenerateSideMesh(Table.Table table) { var sideMesh = new Mesh("Side"); var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints); var rgTexCoord = DragPoint.GetTextureCoords(_data.DragPoints, vVertex); var numVertices = vVertex.Length; var rgNormal = new Vertex2D[numVertices]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var dx = pv1.X - pv2.X; var dy = pv1.Y - pv2.Y; if (dx != 0.0f || dy != 0.0f) { var invLen = 1.0f / MathF.Sqrt(dx * dx + dy * dy); rgNormal[i] = new Vertex2D { X = dy * invLen, Y = dx * invLen }; } else { rgNormal[i] = new Vertex2D { X = 0.0f, Y = 0.0f }; } } var bottom = _data.HeightBottom * table.GetScaleZ() + table.TableHeight; var top = _data.HeightTop * table.GetScaleZ() + table.TableHeight; var offset = 0; // Render side sideMesh.Vertices = new Vertex3DNoTex2[numVertices * 4]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var a = i == 0 ? numVertices - 1 : i - 1; var c = i < numVertices - 1 ? i + 1 : 0; var vNormal = new [] { new Vertex2D(), new Vertex2D() }; if (pv1.Smooth) { vNormal[0].X = (rgNormal[a].X + rgNormal[i].X) * 0.5f; vNormal[0].Y = (rgNormal[a].Y + rgNormal[i].Y) * 0.5f; } else { vNormal[0].X = rgNormal[i].X; vNormal[0].Y = rgNormal[i].Y; } if (pv2.Smooth) { vNormal[1].X = (rgNormal[i].X + rgNormal[c].X) * 0.5f; vNormal[1].Y = (rgNormal[i].Y + rgNormal[c].Y) * 0.5f; } else { vNormal[1].X = rgNormal[i].X; vNormal[1].Y = rgNormal[i].Y; } vNormal[0].Normalize(); vNormal[1].Normalize(); sideMesh.Vertices[offset] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 1] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 2] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 3] = new Vertex3DNoTex2(); sideMesh.Vertices[offset].X = pv1.X; sideMesh.Vertices[offset].Y = pv1.Y; sideMesh.Vertices[offset].Z = bottom; sideMesh.Vertices[offset + 1].X = pv1.X; sideMesh.Vertices[offset + 1].Y = pv1.Y; sideMesh.Vertices[offset + 1].Z = top; sideMesh.Vertices[offset + 2].X = pv2.X; sideMesh.Vertices[offset + 2].Y = pv2.Y; sideMesh.Vertices[offset + 2].Z = top; sideMesh.Vertices[offset + 3].X = pv2.X; sideMesh.Vertices[offset + 3].Y = pv2.Y; sideMesh.Vertices[offset + 3].Z = bottom; if (_data.SideImage != null) { sideMesh.Vertices[offset].Tu = rgTexCoord[i]; sideMesh.Vertices[offset].Tv = 1.0f; sideMesh.Vertices[offset + 1].Tu = rgTexCoord[i]; sideMesh.Vertices[offset + 1].Tv = 0f; sideMesh.Vertices[offset + 2].Tu = rgTexCoord[c]; sideMesh.Vertices[offset + 2].Tv = 0f; sideMesh.Vertices[offset + 3].Tu = rgTexCoord[c]; sideMesh.Vertices[offset + 3].Tv = 1.0f; } sideMesh.Vertices[offset].Nx = vNormal[0].X; sideMesh.Vertices[offset].Ny = -vNormal[0].Y; sideMesh.Vertices[offset].Nz = 0f; sideMesh.Vertices[offset + 1].Nx = vNormal[0].X; sideMesh.Vertices[offset + 1].Ny = -vNormal[0].Y; sideMesh.Vertices[offset + 1].Nz = 0f; sideMesh.Vertices[offset + 2].Nx = vNormal[1].X; sideMesh.Vertices[offset + 2].Ny = -vNormal[1].Y; sideMesh.Vertices[offset + 2].Nz = 0f; sideMesh.Vertices[offset + 3].Nx = vNormal[1].X; sideMesh.Vertices[offset + 3].Ny = -vNormal[1].Y; sideMesh.Vertices[offset + 3].Nz = 0f; offset += 4; } // prepare index buffer for sides var offset2 = 0; sideMesh.Indices = new int[numVertices * 6]; for (var i = 0; i < numVertices; i++) { sideMesh.Indices[i * 6] = offset2; sideMesh.Indices[i * 6 + 1] = offset2 + 1; sideMesh.Indices[i * 6 + 2] = offset2 + 2; sideMesh.Indices[i * 6 + 3] = offset2; sideMesh.Indices[i * 6 + 4] = offset2 + 2; sideMesh.Indices[i * 6 + 5] = offset2 + 3; offset2 += 4; } return(sideMesh); }
private Dictionary <string, Mesh> GenerateMeshes(Table.Table table) { var meshes = new Dictionary <string, Mesh>(); var topMesh = new Mesh("Top"); var sideMesh = new Mesh("Side"); var vVertex = DragPoint.GetRgVertex <RenderVertex2D, CatmullCurve2DCatmullCurveFactory>(_data.DragPoints); var rgTexCoord = DragPoint.GetTextureCoords(_data.DragPoints, vVertex); var numVertices = vVertex.Length; var rgNormal = new Vertex2D[numVertices]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var dx = pv1.X - pv2.X; var dy = pv1.Y - pv2.Y; var invLen = 1.0f / MathF.Sqrt(dx * dx + dy * dy); rgNormal[i] = new Vertex2D { X = dy * invLen, Y = dx * invLen }; } var bottom = _data.HeightBottom * table.GetScaleZ() + table.TableHeight; var top = _data.HeightTop * table.GetScaleZ() + table.TableHeight; var offset = 0; // Render side sideMesh.Vertices = new Vertex3DNoTex2[numVertices * 4]; for (var i = 0; i < numVertices; i++) { var pv1 = vVertex[i]; var pv2 = vVertex[i < numVertices - 1 ? i + 1 : 0]; var a = i == 0 ? numVertices - 1 : i - 1; var c = i < numVertices - 1 ? i + 1 : 0; var vNormal = new [] { new Vertex2D(), new Vertex2D() }; if (pv1.Smooth) { vNormal[0].X = (rgNormal[a].X + rgNormal[i].X) * 0.5f; vNormal[0].Y = (rgNormal[a].Y + rgNormal[i].Y) * 0.5f; } else { vNormal[0].X = rgNormal[i].X; vNormal[0].Y = rgNormal[i].Y; } if (pv2.Smooth) { vNormal[1].X = (rgNormal[i].X + rgNormal[c].X) * 0.5f; vNormal[1].Y = (rgNormal[i].Y + rgNormal[c].Y) * 0.5f; } else { vNormal[1].X = rgNormal[i].X; vNormal[1].Y = rgNormal[i].Y; } vNormal[0].Normalize(); vNormal[1].Normalize(); sideMesh.Vertices[offset] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 1] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 2] = new Vertex3DNoTex2(); sideMesh.Vertices[offset + 3] = new Vertex3DNoTex2(); sideMesh.Vertices[offset].X = pv1.X; sideMesh.Vertices[offset].Y = pv1.Y; sideMesh.Vertices[offset].Z = bottom; sideMesh.Vertices[offset + 1].X = pv1.X; sideMesh.Vertices[offset + 1].Y = pv1.Y; sideMesh.Vertices[offset + 1].Z = top; sideMesh.Vertices[offset + 2].X = pv2.X; sideMesh.Vertices[offset + 2].Y = pv2.Y; sideMesh.Vertices[offset + 2].Z = top; sideMesh.Vertices[offset + 3].X = pv2.X; sideMesh.Vertices[offset + 3].Y = pv2.Y; sideMesh.Vertices[offset + 3].Z = bottom; if (_data.SideImage != null) { sideMesh.Vertices[offset].Tu = rgTexCoord[i]; sideMesh.Vertices[offset].Tv = 1.0f; sideMesh.Vertices[offset + 1].Tu = rgTexCoord[i]; sideMesh.Vertices[offset + 1].Tv = 0f; sideMesh.Vertices[offset + 2].Tu = rgTexCoord[c]; sideMesh.Vertices[offset + 2].Tv = 0f; sideMesh.Vertices[offset + 3].Tu = rgTexCoord[c]; sideMesh.Vertices[offset + 3].Tv = 1.0f; } sideMesh.Vertices[offset].Nx = vNormal[0].X; sideMesh.Vertices[offset].Ny = -vNormal[0].Y; sideMesh.Vertices[offset].Nz = 0f; sideMesh.Vertices[offset + 1].Nx = vNormal[0].X; sideMesh.Vertices[offset + 1].Ny = -vNormal[0].Y; sideMesh.Vertices[offset + 1].Nz = 0f; sideMesh.Vertices[offset + 2].Nx = vNormal[1].X; sideMesh.Vertices[offset + 2].Ny = -vNormal[1].Y; sideMesh.Vertices[offset + 2].Nz = 0f; sideMesh.Vertices[offset + 3].Nx = vNormal[1].X; sideMesh.Vertices[offset + 3].Ny = -vNormal[1].Y; sideMesh.Vertices[offset + 3].Nz = 0f; offset += 4; } // prepare index buffer for sides var offset2 = 0; sideMesh.Indices = new int[numVertices * 6]; for (var i = 0; i < numVertices; i++) { sideMesh.Indices[i * 6] = offset2; sideMesh.Indices[i * 6 + 1] = offset2 + 1; sideMesh.Indices[i * 6 + 2] = offset2 + 2; sideMesh.Indices[i * 6 + 3] = offset2; sideMesh.Indices[i * 6 + 4] = offset2 + 2; sideMesh.Indices[i * 6 + 5] = offset2 + 3; offset2 += 4; } // draw top var vPoly = new List <int>(new int[numVertices]); for (var i = 0; i < numVertices; i++) { vPoly[i] = i; } topMesh.Indices = Mesh.PolygonToTriangles(vVertex, vPoly); var numPolys = topMesh.Indices.Length / 3; if (numPolys == 0) { // no polys to render leave vertex buffer undefined return(meshes); } var heightNotDropped = _data.HeightTop * table.GetScaleZ(); var heightDropped = _data.HeightBottom * table.GetScaleZ() + 0.1; var invTableWidth = 1.0f / table.Width; var invTableHeight = 1.0f / table.Height; Vertex3DNoTex2[][] vertsTop = { new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices], new Vertex3DNoTex2[numVertices] }; for (var i = 0; i < numVertices; i++) { var pv0 = vVertex[i]; vertsTop[0][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = heightNotDropped + table.TableHeight, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[1][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = (float)heightDropped, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = 1.0f }; vertsTop[2][i] = new Vertex3DNoTex2 { X = pv0.X, Y = pv0.Y, Z = _data.HeightBottom, Tu = pv0.X * invTableWidth, Tv = pv0.Y * invTableHeight, Nx = 0, Ny = 0, Nz = -1.0f }; } topMesh.Vertices = vertsTop[0]; if (topMesh.Vertices.Length > 0) { meshes["Top"] = topMesh; } if (System.Math.Abs(top - bottom) > 0.00001f) { meshes["Side"] = sideMesh; } return(meshes); }
private Mesh GenerateFlatRightWall(Table.Table table, RampVertex rv) { var invTableWidth = 1.0f / table.Width; var invTableHeight = 1.0f / table.Height; var numVertices = rv.VertexCount * 2; var numIndices = (rv.VertexCount - 1) * 6; var mesh = new Mesh("RightWall") { Vertices = new Vertex3DNoTex2[numVertices], Indices = new int[numIndices] }; for (var i = 0; i < rv.VertexCount; i++) { var rgv3d1 = new Vertex3DNoTex2(); var rgv3d2 = new Vertex3DNoTex2(); rgv3d1.X = rv.RgvLocal[i].X; rgv3d1.Y = rv.RgvLocal[i].Y; rgv3d1.Z = rv.PointHeights[i] * table.GetScaleZ(); rgv3d2.X = rv.RgvLocal[i].X; rgv3d2.Y = rv.RgvLocal[i].Y; rgv3d2.Z = (rv.PointHeights[i] + _data.RightWallHeightVisible) * table.GetScaleZ(); if (_data.Image != null && _data.ImageWalls) { if (_data.ImageAlignment == RampImageAlignment.ImageModeWorld) { rgv3d1.Tu = rgv3d1.X * invTableWidth; rgv3d1.Tv = rgv3d1.Y * invTableHeight; } else { rgv3d1.Tu = 0; rgv3d1.Tv = rv.PointRatios[i]; } rgv3d2.Tu = rgv3d1.Tu; rgv3d2.Tv = rgv3d1.Tv; } else { rgv3d1.Tu = 0.0f; rgv3d1.Tv = 0.0f; rgv3d2.Tu = 0.0f; rgv3d2.Tv = 0.0f; } mesh.Vertices[i * 2] = rgv3d1; mesh.Vertices[i * 2 + 1] = rgv3d2; if (i == rv.VertexCount - 1) { break; } mesh.Indices[i * 6] = i * 2; mesh.Indices[i * 6 + 1] = i * 2 + 1; mesh.Indices[i * 6 + 2] = i * 2 + 3; mesh.Indices[i * 6 + 3] = i * 2; mesh.Indices[i * 6 + 4] = i * 2 + 3; mesh.Indices[i * 6 + 5] = i * 2 + 2; } Mesh.ComputeNormals(mesh.Vertices, numVertices, mesh.Indices, (rv.VertexCount - 1) * 6); return(mesh); }
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()); }
private Dictionary <string, Mesh> GenerateMeshes(Table.Table table) { var meshes = new Dictionary <string, Mesh>(); var fullMatrix = new Matrix3D(); fullMatrix.RotateZMatrix(MathF.DegToRad(180.0f)); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y); var baseRadius = _data.BaseRadius - _data.RubberThickness; var endRadius = _data.EndRadius - _data.RubberThickness; // 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 = FlipperBaseMesh.Clone(Base); 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 * table.GetScaleZ() + height); meshes[Base] = baseMesh; // rubber if (_data.RubberThickness > 0.0) { var rubberMesh = FlipperBaseMesh.Clone(Rubber); 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, 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, 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, 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, new Vertex2D(0, _data.FlipperRadius)); } } } rubberMesh.Transform(fullMatrix, null, z => z * _data.RubberWidth * table.GetScaleZ() + (height + _data.RubberHeight)); meshes[Rubber] = rubberMesh; } return(meshes); }
private Dictionary <string, Mesh> GenerateMeshes(Table.Table table) { var meshes = new Dictionary <string, Mesh>(); var fullMatrix = new Matrix3D(); fullMatrix.RotateZMatrix(MathF.DegToRad(180.0f)); var height = table.GetSurfaceHeight(_data.Surface, _data.Center.X, _data.Center.Y); const float baseScale = 10.0f; const float tipScale = 10.0f; var baseRadius = _data.BaseRadius - _data.RubberThickness; var endRadius = _data.EndRadius - _data.RubberThickness; // base and tip var baseMesh = FlipperBaseMesh.Clone("Base"); for (var t = 0; t < 13; t++) { foreach (var v in baseMesh.Vertices) { if (v.X == VertsBaseBottom[t].X && v.Y == VertsBaseBottom[t].Y && v.Z == VertsBaseBottom[t].Z) { v.X *= baseRadius * baseScale; v.Y *= baseRadius * baseScale; } if (v.X == VertsTipBottom[t].X && v.Y == VertsTipBottom[t].Y && v.Z == VertsTipBottom[t].Z) { v.X *= endRadius * tipScale; v.Y *= endRadius * tipScale; v.Y += _data.FlipperRadius - endRadius * 7.9f; } if (v.X == VertsBaseTop[t].X && v.Y == VertsBaseTop[t].Y && v.Z == VertsBaseTop[t].Z) { v.X *= baseRadius * baseScale; v.Y *= baseRadius * baseScale; } if (v.X == VertsTipTop[t].X && v.Y == VertsTipTop[t].Y && v.Z == VertsTipTop[t].Z) { v.X *= endRadius * tipScale; v.Y *= endRadius * tipScale; v.Y += _data.FlipperRadius - endRadius * 7.9f; } } } baseMesh.Transform(fullMatrix, null, z => z * _data.Height * table.GetScaleZ() + height); meshes["Base"] = baseMesh; // rubber if (_data.RubberThickness > 0.0) { const float rubberBaseScale = 10.0f; const float rubberTipScale = 10.0f; var rubberMesh = FlipperBaseMesh.Clone("Rubber"); for (var t = 0; t < 13; t++) { foreach (var v in rubberMesh.Vertices) { if (v.X == VertsBaseBottom[t].X && v.Y == VertsBaseBottom[t].Y && v.Z == VertsBaseBottom[t].Z) { v.X = v.X * _data.BaseRadius * rubberBaseScale; v.Y = v.Y * _data.BaseRadius * rubberBaseScale; } if (v.X == VertsTipBottom[t].X && v.Y == VertsTipBottom[t].Y && v.Z == VertsTipBottom[t].Z) { v.X = v.X * _data.EndRadius * rubberTipScale; v.Y = v.Y * _data.EndRadius * rubberTipScale; v.Y = v.Y + _data.FlipperRadius - _data.EndRadius * 7.9f; } if (v.X == VertsBaseTop[t].X && v.Y == VertsBaseTop[t].Y && v.Z == VertsBaseTop[t].Z) { v.X = v.X * _data.BaseRadius * rubberBaseScale; v.Y = v.Y * _data.BaseRadius * rubberBaseScale; } if (v.X == VertsTipTop[t].X && v.Y == VertsTipTop[t].Y && v.Z == VertsTipTop[t].Z) { v.X = v.X * _data.EndRadius * rubberTipScale; v.Y = v.Y * _data.EndRadius * rubberTipScale; v.Y = v.Y + _data.FlipperRadius - _data.EndRadius * 7.9f; } } } rubberMesh.Transform(fullMatrix, null, z => z * _data.RubberWidth * table.GetScaleZ() + (height + _data.RubberHeight)); meshes["Rubber"] = rubberMesh; } return(meshes); }