public static Light GetDefault(string name, float x, float y) { var lightData = new LightData(name, x, y) { DragPoints = new[] { new DragPointData(x, y - 50f) { IsSmooth = true }, new DragPointData(x - 50f * MathF.Cos(MathF.PI / 4), y - 50f * MathF.Sin(MathF.PI / 4)) { IsSmooth = true }, new DragPointData(x - 50f, y) { IsSmooth = true }, new DragPointData(x - 50f * MathF.Cos(MathF.PI / 4), y + 50f * MathF.Sin(MathF.PI / 4)) { IsSmooth = true }, new DragPointData(x, y + 50f) { IsSmooth = true }, new DragPointData(x + 50f * MathF.Cos(MathF.PI / 4), y + 50f * MathF.Sin(MathF.PI / 4)) { IsSmooth = true }, new DragPointData(x + 50f, y) { IsSmooth = true }, new DragPointData(x + 50f * MathF.Cos(MathF.PI / 4), y - 50f * MathF.Sin(MathF.PI / 4)) { IsSmooth = true }, } }; return(new Light(lightData)); }
private Mesh CalculateBuiltinOriginal() { var mesh = new Mesh(_data.Name); // this recalculates the Original Vertices -> should be only called, when sides are altered. var outerRadius = -0.5f / MathF.Cos(MathF.PI / _data.Sides); var addAngle = 2.0f * MathF.PI / _data.Sides; var offsAngle = MathF.PI / _data.Sides; var minX = Constants.FloatMax; var minY = Constants.FloatMax; var maxX = -Constants.FloatMax; var maxY = -Constants.FloatMax; mesh.Vertices = new Vertex3DNoTex2[4 * _data.Sides + 2]; // middle point top mesh.Vertices[0] = new Vertex3DNoTex2 { X = 0.0f, Y = 0.0f, Z = 0.5f }; // middle point bottom mesh.Vertices[_data.Sides + 1] = new Vertex3DNoTex2 { X = 0.0f, Y = 0.0f, Z = -0.5f }; for (var i = 0; i < _data.Sides; ++i) { var currentAngle = addAngle * i + offsAngle; // calculate Top var topVert = new Vertex3DNoTex2 { // top point at side X = MathF.Sin(currentAngle) * outerRadius, Y = MathF.Cos(currentAngle) * outerRadius, Z = 0.5f }; mesh.Vertices[i + 1] = topVert; // calculate bottom var bottomVert = new Vertex3DNoTex2 { // bottom point at side X = topVert.X, Y = topVert.Y, Z = -0.5f }; mesh.Vertices[i + 1 + _data.Sides + 1] = bottomVert; // calculate sides mesh.Vertices[_data.Sides * 2 + 2 + i] = topVert; // sideTopVert mesh.Vertices[_data.Sides * 3 + 2 + i] = bottomVert; // sideBottomVert // calculate bounds for X and Y if (topVert.X < minX) { minX = topVert.X; } if (topVert.X > maxX) { maxX = topVert.X; } if (topVert.Y < minY) { minY = topVert.Y; } if (topVert.Y > maxY) { maxY = topVert.Y; } } // these have to be replaced for image mapping var middle = mesh.Vertices[0]; // middle point top middle.Tu = 0.25f; // /4 middle.Tv = 0.25f; // /4 middle = mesh.Vertices[_data.Sides + 1]; // middle point bottom middle.Tu = 0.25f * 3.0f; // /4*3 middle.Tv = 0.25f; // /4 var invX = 0.5f / (maxX - minX); var invY = 0.5f / (maxY - minY); var invS = 1.0f / _data.Sides; for (var i = 0; i < _data.Sides; i++) { var topVert = mesh.Vertices[i + 1]; // top point at side topVert.Tu = (topVert.X - minX) * invX; topVert.Tv = (topVert.Y - minY) * invY; var bottomVert = mesh.Vertices[i + 1 + _data.Sides + 1]; // bottom point at side bottomVert.Tu = topVert.Tu + 0.5f; bottomVert.Tv = topVert.Tv; var sideTopVert = mesh.Vertices[_data.Sides * 2 + 2 + i]; var sideBottomVert = mesh.Vertices[_data.Sides * 3 + 2 + i]; sideTopVert.Tu = i * invS; sideTopVert.Tv = 0.5f; sideBottomVert.Tu = sideTopVert.Tu; sideBottomVert.Tv = 1.0f; } // So how many indices are needed? // 3 per Triangle top - we have m_sides triangles -> 0, 1, 2, 0, 2, 3, 0, 3, 4, ... // 3 per Triangle bottom - we have m_sides triangles // 6 per Side at the side (two triangles form a rectangle) - we have m_sides sides // == 12 * m_sides // * 2 for both cullings (m_DrawTexturesInside == true) // == 24 * m_sides // this will also be the initial sorting, when depths, Vertices and Indices are recreated, because calculateRealTimeOriginal is called. // 2 restore indices // check if anti culling is enabled: if (_data.DrawTexturesInside) { mesh.Indices = new int[_data.Sides * 24]; // draw yes everything twice // restore indices for (var i = 0; i < _data.Sides; i++) { var tmp = i == _data.Sides - 1 ? 1 : i + 2; // wrapping around // top mesh.Indices[i * 6] = 0; mesh.Indices[i * 6 + 1] = i + 1; mesh.Indices[i * 6 + 2] = tmp; mesh.Indices[i * 6 + 3] = 0; mesh.Indices[i * 6 + 4] = tmp; mesh.Indices[i * 6 + 5] = i + 1; var tmp2 = tmp + 1; // bottom mesh.Indices[6 * (i + _data.Sides)] = _data.Sides + 1; mesh.Indices[6 * (i + _data.Sides) + 1] = _data.Sides + tmp2; mesh.Indices[6 * (i + _data.Sides) + 2] = _data.Sides + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 3] = _data.Sides + 1; mesh.Indices[6 * (i + _data.Sides) + 4] = _data.Sides + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 5] = _data.Sides + tmp2; // sides mesh.Indices[12 * (i + _data.Sides)] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 1] = _data.Sides * 2 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 2] = _data.Sides * 3 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 3] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 4] = _data.Sides * 3 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 5] = _data.Sides * 3 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 6] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 7] = _data.Sides * 3 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 8] = _data.Sides * 2 + 2 + i; mesh.Indices[12 * (i + _data.Sides) + 9] = _data.Sides * 2 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 10] = _data.Sides * 3 + tmp2; mesh.Indices[12 * (i + _data.Sides) + 11] = _data.Sides * 3 + 2 + i; } } else { // only no out-facing polygons // restore indices mesh.Indices = new int[_data.Sides * 12]; for (var i = 0; i < _data.Sides; i++) { var tmp = i == _data.Sides - 1 ? 1 : i + 2; // wrapping around // top mesh.Indices[i * 3] = 0; mesh.Indices[i * 3 + 2] = i + 1; mesh.Indices[i * 3 + 1] = tmp; //SetNormal(mesh.Vertices[0], &mesh.Indices[i+3], 3); // see below var tmp2 = tmp + 1; // bottom mesh.Indices[3 * (i + _data.Sides)] = _data.Sides + 1; mesh.Indices[3 * (i + _data.Sides) + 1] = _data.Sides + 2 + i; mesh.Indices[3 * (i + _data.Sides) + 2] = _data.Sides + tmp2; //SetNormal(mesh.Vertices[0], &mesh.Indices[3*(i+_data.Sides)], 3); // see below // sides mesh.Indices[6 * (i + _data.Sides)] = _data.Sides * 2 + tmp2; mesh.Indices[6 * (i + _data.Sides) + 1] = _data.Sides * 3 + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 2] = _data.Sides * 2 + 2 + i; mesh.Indices[6 * (i + _data.Sides) + 3] = _data.Sides * 2 + tmp2; mesh.Indices[6 * (i + _data.Sides) + 4] = _data.Sides * 3 + tmp2; mesh.Indices[6 * (i + _data.Sides) + 5] = _data.Sides * 3 + 2 + i; } } //SetNormal(mesh.Vertices[0], &mesh.Indices[0], m_mesh.NumIndices()); // SetNormal only works for plane polygons Mesh.ComputeNormals(mesh.Vertices, mesh.Vertices.Length, mesh.Indices, mesh.Indices.Length); return(mesh); }
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); }
public Vertex3DNoTex2[] BuildRodVertices(int frame) { if (_lathePoints == 0) { CalculateArraySizes(); } var vertices = new Vertex3DNoTex2[_latheVts]; var yTip = _beginY + _dyPerFrame * frame; var tu = 0.51f; var stepU = 1.0f / _circlePoints; var i = 0; for (var l = 0; l < _circlePoints; l++, tu += stepU) { // Go down the long axis, adding a vertex for each point // in the descriptor list at the current lathe angle. if (tu > 1.0f) { tu -= 1.0f; } var angle = (float)(MathF.PI * 2.0) / _circlePoints * l; var sn = MathF.Sin(angle); var cs = MathF.Cos(angle); for (var m = 0; m < _lathePoints; m++) { ref var c = ref _desc.c[m]; // get the current point's coordinates var y = c.y + yTip; var r = c.r; var tv = c.tv; // the last coordinate is always the bottom of the rod if (m + 1 == _lathePoints) { // set the end point y = _rodY; // Figure the texture mapping for the rod position. This is // important because we draw the rod with varying length - // the part that's pulled back beyond the 'rodY' point is // hidden. We want the texture to maintain the same apparent // position and scale in each frame, so we need to figure the // proportional point of the texture at our cut-off point on // the object surface. var ratio = frame * _invScale; tv = vertices[m - 1].Tv + (tv - vertices[m - 1].Tv) * ratio; } vertices[i++] = new Vertex3DNoTex2 { X = r * (sn * _data.Width) + _data.Center.X, Y = y, Z = (r * (cs * _data.Width) + _data.Width + _zHeight) * _zScale, Nx = c.nx * sn, Ny = c.ny, Nz = c.nx * cs, Tu = tu, Tv = tv }; } }