private static IEnumerable <ITriangle> GetBeveledTriangle_Sides(ITriangle triangle, double normalHeight, double sideDepth) { Point3D tip = triangle.GetCenterPoint() + (triangle.NormalUnit * normalHeight); Point3D[] extended = triangle.PointArray. Select(o => o + ((o - tip).ToUnit() * sideDepth)). ToArray(); Point3D[] allPoints = triangle. PointArray. Concat(extended). ToArray(); List <TriangleIndexed> retVal = new List <TriangleIndexed>(); // 0-1 retVal.Add(new TriangleIndexed(0, 1, 3, allPoints)); retVal.Add(new TriangleIndexed(1, 4, 3, allPoints)); // 1-2 retVal.Add(new TriangleIndexed(1, 2, 4, allPoints)); retVal.Add(new TriangleIndexed(2, 5, 4, allPoints)); // 2-0 retVal.Add(new TriangleIndexed(2, 0, 5, allPoints)); retVal.Add(new TriangleIndexed(0, 3, 5, allPoints)); return(retVal); }
/// <summary> /// This takes a triangle, reduces its size, and creates sloped sides /// </summary> /// <param name="scale">This is the percent to reduce the incoming triangle by</param> /// <param name="normalHeight"> /// A line is drawn from a point above the triangle to each vertex. The smaller this height, the more angled out /// the beveled edges will be (if this height is infinity, the walls would be vertical) /// </param> /// <param name="sideDepth"> /// How tall the edges should be (you want them deep enough that you don't see the bottom edge, but if too deep, they /// will poke through the back side of the sphere) /// </param> private static ITriangle[] GetBeveledTriangle(ITriangle triangle, double scale, double normalHeight, double sideDepth) { Point3D center = triangle.GetCenterPoint(); Triangle outerPlate = new Triangle( center + ((triangle.Point0 - center) * scale), center + ((triangle.Point1 - center) * scale), center + ((triangle.Point2 - center) * scale)); List <ITriangle> retVal = new List <ITriangle>(); retVal.Add(outerPlate); retVal.AddRange(GetBeveledTriangle_Sides(outerPlate, normalHeight, sideDepth)); return(retVal.ToArray()); }
/// <summary> /// This can be used to visualize a plane. Drawing a single square is difficult to visualize the perspective, so this draws /// a set of tiles, and a border. It's always square to also help visualize perspective. Also, wpf doesn't deal with semi /// transparency very well, so that's why this model is mostly gaps /// NOTE: Most of the methods return meshes, this returns an entire model /// </summary> /// <param name="center"> /// This gives a chance to be explicit about the center of the drawn plane. There is no check to be sure center lies on the plane, /// but it should. (this was added because Math3D.GetPlane() doesn't build a triangle centered on the point passed in) /// If this is left null, then the center of the triangle will be used /// </param> public static Model3D GetPlane(ITriangle plane, double size, Color color, Color? reflectiveColor = null, int numCells = 12, Point3D? center = null) { double halfSize = size / 2; double cellSize = size / numCells; double tileSizeHalf = cellSize / (4d * 2d); Model3DGroup retVal = new Model3DGroup(); #region Border var segments = new[] { Tuple.Create(new Point3D(-halfSize, -halfSize, 0), new Point3D(halfSize, -halfSize, 0)), Tuple.Create(new Point3D(halfSize, -halfSize, 0), new Point3D(halfSize, halfSize, 0)), Tuple.Create(new Point3D(halfSize, halfSize, 0), new Point3D(-halfSize, halfSize, 0)), Tuple.Create(new Point3D(-halfSize, halfSize, 0), new Point3D(-halfSize, -halfSize, 0)), }; Color lineColor = Color.FromArgb(96, color.R, color.G, color.B); //double lineThickness = .015; double lineThickness = size / 666.666666667d; foreach (var segment in segments) { retVal.Children.Add(new Game.HelperClassesWPF.Primitives3D.BillboardLine3D() { Color = lineColor, IsReflectiveColor = false, Thickness = lineThickness, FromPoint = segment.Item1, ToPoint = segment.Item2 }.Model); } #endregion #region Tiles // Material MaterialGroup materials = new MaterialGroup(); materials.Children.Add(new DiffuseMaterial(new SolidColorBrush(Color.FromArgb(48, color.R, color.G, color.B)))); if (reflectiveColor != null) { materials.Children.Add(new SpecularMaterial(new SolidColorBrush(Color.FromArgb(96, reflectiveColor.Value.R, reflectiveColor.Value.G, reflectiveColor.Value.B)), 5d)); } // Tiles for (int xCntr = 0; xCntr <= numCells; xCntr++) { double x = -halfSize + (xCntr * cellSize); double left = xCntr == 0 ? 0 : -tileSizeHalf; double right = xCntr == numCells ? 0 : tileSizeHalf; for (int yCntr = 0; yCntr <= numCells; yCntr++) { double y = -halfSize + (yCntr * cellSize); double up = yCntr == 0 ? 0 : -tileSizeHalf; double down = yCntr == numCells ? 0 : tileSizeHalf; // Geometry Model GeometryModel3D geometry = new GeometryModel3D(); geometry.Material = materials; geometry.BackMaterial = materials; geometry.Geometry = UtilityWPF.GetSquare2D(new Point(x + left, y + up), new Point(x + right, y + down)); retVal.Children.Add(geometry); } } #endregion Transform3DGroup transform = new Transform3DGroup(); transform.Children.Add(new RotateTransform3D(new QuaternionRotation3D(Math3D.GetRotation(new Vector3D(0, 0, 1), plane.Normal)))); if (center == null) { transform.Children.Add(new TranslateTransform3D(plane.GetCenterPoint().ToVector())); } else { transform.Children.Add(new TranslateTransform3D(center.Value.ToVector())); } retVal.Transform = transform; return retVal; }