public MeshGradeShape(EdgeBlit edge, ICurve curve, TriangleUtil.Triangle[] tri) { var box = BoundingBoxD.CreateInvalid(); foreach (var k in tri) { box.Include(k.Origin); box.Include(k.Origin + k.Edge1); box.Include(k.Origin + k.Edge2); } Box = box.Inflate(0.5f); _tris = tri; _edge = edge; _curve = curve; }
public MeshGradeShape CreateShape(EdgeBlit e, bool invertHeight) { var h = Height; if (invertHeight) { h *= -1; } switch (Type) { case MyObjectBuilder_RailGradeComponentDefinition.Shape.GradeType.Tunnel: return(MeshGradeShape.CreateTunnelShape(e, Width, RelaxAngleRadians, VerticalOffset, Segments, h, EndPadding)); case MyObjectBuilder_RailGradeComponentDefinition.Shape.GradeType.Grade: default: return(MeshGradeShape.CreateGradeShape(e, Width, RelaxAngleRadians, VerticalOffset, Segments, h, EndPadding)); } }
public static MeshGradeShape CreateGradeShape(EdgeBlit edge, float width, float relaxAngle, float shiftUp, int segments, float maxDepth, float endPadding) { var curve = edge.Curve.Convert(); var tris = new List <TriangleUtil.Triangle>(); var lastCross = new Vector3D[4]; var currCross = new Vector3D[4]; for (var i = 0; i <= segments; i++) { var t = i / (float)segments; var loc = curve.Sample(t); var tangent = (Vector3)curve.SampleDerivative(t); tangent.Normalize(); if (i == 0) { loc -= tangent * endPadding; } if (i == segments) { loc += tangent * endPadding; } var up = Vector3.Lerp(edge.FromUp, edge.ToUp, t); up.Normalize(); loc += shiftUp * up; var normal = Vector3.Cross(up, tangent); normal.Normalize(); var perturbLow = Vector3.Zero; if (i == 0 || i == segments) { var n = i == 0 ? -tangent : tangent; perturbLow = (float)Math.Cos(relaxAngle) * n * Math.Abs(maxDepth); } for (var j = -1; j <= 1; j += 2) { var offset = j + 1; var origin = loc + (width / 2) * j * normal; var rot = Matrix.CreateFromAxisAngle(tangent, -j * Math.Sign(maxDepth) * relaxAngle); var pnorm = Vector3.TransformNormal(up, rot); var cotan = Vector3.Cross(pnorm, tangent); cotan.Normalize(); cotan *= -Math.Sign(Vector3.Dot(cotan, up)); var p2 = origin + maxDepth * cotan + perturbLow; if (i > 0) { tris.Add(new TriangleUtil.Triangle(origin, lastCross[offset], lastCross[offset + 1], pnorm)); if ((p2 - lastCross[offset + 1]).Dot(tangent) > 0) { tris.Add(new TriangleUtil.Triangle(origin, lastCross[offset + 1], p2, pnorm)); } else { p2 = lastCross[offset + 1]; } } currCross[offset] = origin; currCross[offset + 1] = p2; } if (i > 0) { tris.Add(new TriangleUtil.Triangle(currCross[0], lastCross[0], lastCross[2], up)); tris.Add(new TriangleUtil.Triangle(currCross[0], lastCross[2], currCross[2], up)); tris.Add(new TriangleUtil.Triangle(currCross[1], lastCross[1], lastCross[3], -up)); tris.Add(new TriangleUtil.Triangle(currCross[1], lastCross[3], currCross[3], -up)); } if (i == 0 || i == segments) { var n = i == 0 ? -tangent : tangent; tris.Add(new TriangleUtil.Triangle(currCross[0], currCross[2], currCross[3], n)); tris.Add(new TriangleUtil.Triangle(currCross[0], currCross[3], currCross[1], n)); } var tmp = lastCross; lastCross = currCross; currCross = tmp; } return(new MeshGradeShape(edge, curve, tris.ToArray())); }
public static MeshGradeShape CreateTunnelShape(EdgeBlit edge, float width, float relaxAngle, float shiftUp, int segments, float height, float endPadding) { var curve = edge.Curve.Convert(); var tris = new List <TriangleUtil.Triangle>(); // {-Level, -OuterEdge, -Ceiling, +Level, +OuterEdge, +Ceiling} var lastCross = new Vector3D[6]; var currCross = new Vector3D[6]; var halfHeight = height / 2; var dropTop = height / 5; var ceilingPrevious = Vector3D.Zero; for (var i = 0; i <= segments; i++) { var t = i / (float)segments; var loc = curve.Sample(t); var tangent = (Vector3)curve.SampleDerivative(t); tangent.Normalize(); if (i == 0) { loc -= tangent * endPadding; } if (i == segments) { loc += tangent * endPadding; } var up = Vector3.Lerp(edge.FromUp, edge.ToUp, t); up.Normalize(); loc += shiftUp * up; var ceilingTotal = loc - up * height; var normal = Vector3.Cross(up, tangent); normal.Normalize(); var perturbLow = Vector3.Zero; if (i == 0 || i == segments) { var n = i == 0 ? -tangent : tangent; perturbLow = (float)Math.Cos(relaxAngle) * n * Math.Abs(halfHeight); } for (var j = -1; j <= 1; j += 2) { var offset = (j + 1) * 3 / 2; var origin = loc + (width / 2) * j * normal; var rot = Matrix.CreateFromAxisAngle(tangent, -j * Math.Sign(halfHeight) * relaxAngle); var pnorm = Vector3.TransformNormal(up, rot); var cotan = Vector3.Cross(pnorm, tangent); cotan.Normalize(); cotan *= -Math.Sign(Vector3.Dot(cotan, up)); var p2 = origin + halfHeight * cotan + perturbLow; var ceilingEdge = origin - up * (height - dropTop); if (i > 0) { // side faces, lower tris.Add(new TriangleUtil.Triangle(origin, lastCross[offset], lastCross[offset + 1], pnorm)); var dissolvedOuterEdge = (p2 - lastCross[offset + 1]).Dot(tangent) <= 0; if (dissolvedOuterEdge) { p2 = lastCross[offset + 1]; } else { tris.Add(new TriangleUtil.Triangle(origin, lastCross[offset + 1], p2, pnorm)); } var dissolvedCeilingEdge = (ceilingEdge - lastCross[offset + 2]).Dot(tangent) <= 0; if (dissolvedCeilingEdge) { ceilingEdge = lastCross[offset + 2]; } // side faces, upper: if (!dissolvedCeilingEdge) { tris.Add(new TriangleUtil.Triangle(lastCross[offset + 1], lastCross[offset + 2], ceilingEdge, pnorm)); } if (!dissolvedOuterEdge) { tris.Add(new TriangleUtil.Triangle(lastCross[offset + 1], p2, ceilingEdge, pnorm)); } } currCross[offset] = origin; currCross[offset + 1] = p2; currCross[offset + 2] = ceilingEdge; } if (i > 0) { // top tris.Add(new TriangleUtil.Triangle(currCross[0], lastCross[0], lastCross[3], -up)); tris.Add(new TriangleUtil.Triangle(currCross[0], lastCross[3], currCross[3], -up)); // bottom tris.Add(new TriangleUtil.Triangle(currCross[2], lastCross[2], ceilingPrevious, up)); tris.Add(new TriangleUtil.Triangle(currCross[2], ceilingPrevious, ceilingTotal, up)); tris.Add(new TriangleUtil.Triangle(currCross[5], lastCross[5], ceilingPrevious, up)); tris.Add(new TriangleUtil.Triangle(currCross[5], ceilingPrevious, ceilingTotal, up)); } // end caps if (i == 0 || i == segments) { var n = i == 0 ? -tangent : tangent; var avg = (currCross[0] + currCross[1] + currCross[2] + currCross[3] + currCross[4] + currCross[5]) / 6; tris.Add(new TriangleUtil.Triangle(currCross[0], currCross[1], avg, n)); tris.Add(new TriangleUtil.Triangle(currCross[1], currCross[2], avg, n)); tris.Add(new TriangleUtil.Triangle(currCross[2], ceilingTotal, avg, n)); tris.Add(new TriangleUtil.Triangle(ceilingTotal, currCross[5], avg, n)); tris.Add(new TriangleUtil.Triangle(currCross[5], currCross[4], avg, n)); tris.Add(new TriangleUtil.Triangle(currCross[4], currCross[3], avg, n)); tris.Add(new TriangleUtil.Triangle(currCross[3], currCross[0], avg, n)); } var tmp = lastCross; lastCross = currCross; currCross = tmp; ceilingPrevious = ceilingTotal; } return(new MeshGradeShape(edge, curve, tris.ToArray())); }