public Sphere(ESphere type, IModule module, Color[] colors, float diameter = 2048, int tessellation = 128) { Vertices = new List<VertexPositionNormalColor>(); Indices = new List<short>(); if (tessellation < 3 || tessellation > 128) { throw new ArgumentOutOfRangeException(nameof(tessellation)); } var verticalSegments = tessellation; var horizontalSegments = tessellation * 2; var radius = diameter / 2; var noise = module.GetPlanet(horizontalSegments, verticalSegments); switch (type) { case ESphere.Terrain: { #region Terrain Vertex AddVertex(Vector3.Down * radius * (1.0f + (float)noise[0, 0]), Vector3.Down, Color.White); for (var i = 0; i < verticalSegments - 1; i++) { var latitude = ((i + 1) * MathHelper.Pi / verticalSegments) - MathHelper.PiOver2; var dy = (float)Math.Sin(latitude); var dxz = (float)Math.Cos(latitude); for (var j = 0; j < horizontalSegments; j++) { var longitude = j * MathHelper.TwoPi / horizontalSegments; var dx = (float)Math.Cos(longitude) * dxz; var dz = (float)Math.Sin(longitude) * dxz; var normal = new Vector3(dx, dy, dz); var value = 1.0f + (float)noise[j, i]; var color = colors.GetColorAt(value - 1.0f); var v = value; AddVertex(normal * radius * v, normal * v, color); } } AddVertex(Vector3.Up * radius * (1.0f + (float)noise[horizontalSegments - 1, verticalSegments - 1]), Vector3.Up, Color.White); #endregion break; } case ESphere.Ocean: { #region Ocean Vertex AddVertex(Vector3.Down * radius, Vector3.Down, Color.White); for (var i = 0; i < verticalSegments - 1; i++) { var latitude = ((i + 1) * MathHelper.Pi / verticalSegments) - MathHelper.PiOver2; var dy = (float)Math.Sin(latitude); var dxz = (float)Math.Cos(latitude); for (var j = 0; j < horizontalSegments; j++) { var longitude = j * MathHelper.TwoPi / horizontalSegments; var dx = (float)Math.Cos(longitude) * dxz; var dz = (float)Math.Sin(longitude) * dxz; var normal = new Vector3(dx, dy, dz); AddVertex(normal * radius, normal, colors.GetColorAt(0.0d)); } } AddVertex(Vector3.Up * radius, Vector3.Up, Color.White); #endregion break; } case ESphere.Sky: { #region Sky Vertex AddVertex(Vector3.Down * radius, Vector3.Down, Color.White); for (var i = 0; i < verticalSegments - 1; i++) { var latitude = ((i + 1) * MathHelper.Pi / verticalSegments) - MathHelper.PiOver2; var dy = (float)Math.Sin(latitude); var dxz = (float)Math.Cos(latitude); for (var j = 0; j < horizontalSegments; j++) { var longitude = j * MathHelper.TwoPi / horizontalSegments; var dx = (float)Math.Cos(longitude) * dxz; var dz = (float)Math.Sin(longitude) * dxz; var normal = new Vector3(dx, dy, dz); var value = (float)noise[j, i]; var color = colors.GetColorAt(value); AddVertex(normal * radius, normal, color); } } AddVertex(Vector3.Up * radius, Vector3.Up, Color.White); #endregion break; } default: { throw new InvalidEnumArgumentException(nameof(type)); } } #region Index for (var i = 0; i < horizontalSegments; i++) { AddIndex(0); AddIndex(1 + (i + 1) % horizontalSegments); AddIndex(1 + i); } for (var i = 0; i < verticalSegments - 2; i++) { for (var j = 0; j < horizontalSegments; j++) { var nextI = i + 1; var nextJ = (j + 1) % horizontalSegments; AddIndex(1 + i * horizontalSegments + j); AddIndex(1 + i * horizontalSegments + nextJ); AddIndex(1 + nextI * horizontalSegments + j); AddIndex(1 + i * horizontalSegments + nextJ); AddIndex(1 + nextI * horizontalSegments + nextJ); AddIndex(1 + nextI * horizontalSegments + j); } } for (var i = 0; i < horizontalSegments; i++) { var currentVertex = Vertices.Count; AddIndex(currentVertex - 1); AddIndex(currentVertex - 2 - (i + 1) % horizontalSegments); AddIndex(currentVertex - 2 - i); } #endregion InitializePrimitive(Game.Instance.GraphicsDevice); }