//--------------------// #region Quad /// <summary> /// Creates a new <see cref="Mesh"/> representing a textured 2D quad. /// </summary> /// <param name="device">The <see cref="Device"/> to create the <see cref="Mesh"/> in.</param> /// <param name="width">The width of the quad.</param> /// <param name="height">The height of the quad.</param> public static Mesh Quad(Device device, float width, float height) { #region Sanity checks if (device == null) { throw new ArgumentNullException(nameof(device)); } #endregion var vertexes = new[] { new PositionTextured(new Vector3(-width / 2, -height / 2, 0), 0, 0), new PositionTextured(new Vector3(-width / 2, height / 2, 0), 0, 1), new PositionTextured(new Vector3(width / 2, -height / 2, 0), 1, 0), new PositionTextured(new Vector3(width / 2, height / 2, 0), 1, 1) }; short[] indexes = { 0, 1, 3, 3, 2, 0 }; var mesh = new Mesh(device, indexes.Length / 3, vertexes.Length, MeshFlags.Managed, PositionTextured.Format); BufferHelper.WriteVertexBuffer(mesh, vertexes); BufferHelper.WriteIndexBuffer(mesh, indexes); MeshHelper.GenerateNormalsAndTangents(device, ref mesh, false); return(mesh); }
/// <summary> /// Creates a model of a textured round disc with a hole in the middle. /// </summary> /// <param name="device">The <see cref="Device"/> to create the mesh in.</param> /// <param name="radiusInner">The radius of the inner circle of the ring.</param> /// <param name="radiusOuter">The radius of the outer circle of the ring.</param> /// <param name="height">The height of the ring.</param> /// <param name="segments">The number of segments the ring shall consist of.</param> public static Mesh Disc(Device device, float radiusInner, float radiusOuter, float height, int segments) { #region Sanity checks if (device == null) { throw new ArgumentNullException(nameof(device)); } #endregion const float tuInner = 0, tuOuter = 1; Log.Info("Generate predefined model: Disc"); var posInner = new Vector3(radiusInner, 0, 0); var posOuter = new Vector3(radiusOuter, 0, 0); #region Generate vertexes int vertCount = 0; var step = (float)(Math.PI * 2 / segments); var vertexes = new PositionTextured[segments * 4]; for (int i = 0; i < segments; i++) { vertexes[vertCount++] = new PositionTextured(posInner.X, posInner.Y - height / 2, posInner.Z, tuInner, 0); vertexes[vertCount++] = new PositionTextured(posInner.X, posInner.Y + height / 2, posInner.Z, tuInner, 0); vertexes[vertCount++] = new PositionTextured(posOuter.X, posOuter.Y - height / 2, posOuter.Z, tuOuter, 0); vertexes[vertCount++] = new PositionTextured(posOuter.X, posOuter.Y + height / 2, posOuter.Z, tuOuter, 0); // Increment rotation posInner = Vector3.TransformCoordinate(posInner, Matrix.RotationY(step)); posOuter = Vector3.TransformCoordinate(posOuter, Matrix.RotationY(step)); } #endregion #region Generate indexes int indexCount = 0; var indexes = new short[segments * 24]; for (int i = 0; i < segments; i++) { short innerBottom1 = (short)(i * 4), innerTop1 = (short)(i * 4 + 1); short outerBottom1 = (short)(i * 4 + 2), outerTop1 = (short)(i * 4 + 3); short innerBottom2 = (short)(i * 4 + 4), innerTop2 = (short)(i * 4 + 5); short outerBottom2 = (short)(i * 4 + 6), outerTop2 = (short)(i * 4 + 7); if (innerBottom2 >= vertexes.Length) { innerBottom2 -= (short)vertexes.Length; } if (innerTop2 >= vertexes.Length) { innerTop2 -= (short)vertexes.Length; } if (outerBottom2 >= vertexes.Length) { outerBottom2 -= (short)vertexes.Length; } if (outerTop2 >= vertexes.Length) { outerTop2 -= (short)vertexes.Length; } // Bottom 2 triangles indexes[indexCount++] = innerBottom1; indexes[indexCount++] = innerBottom2; indexes[indexCount++] = outerBottom2; indexes[indexCount++] = innerBottom1; indexes[indexCount++] = outerBottom2; indexes[indexCount++] = outerBottom1; // Top 2 triangles indexes[indexCount++] = innerTop1; indexes[indexCount++] = outerTop2; indexes[indexCount++] = innerTop2; indexes[indexCount++] = innerTop1; indexes[indexCount++] = outerTop1; indexes[indexCount++] = outerTop2; // Inner 2 triangles indexes[indexCount++] = innerTop1; indexes[indexCount++] = innerBottom2; indexes[indexCount++] = innerBottom1; indexes[indexCount++] = innerTop1; indexes[indexCount++] = innerTop2; indexes[indexCount++] = innerBottom2; // Outer 2 triangles indexes[indexCount++] = outerBottom1; indexes[indexCount++] = outerBottom2; indexes[indexCount++] = outerTop1; indexes[indexCount++] = outerBottom2; indexes[indexCount++] = outerTop2; indexes[indexCount++] = outerTop1; } #endregion var mesh = new Mesh(device, indexes.Length / 3, vertexes.Length, MeshFlags.Managed, PositionTextured.Format); BufferHelper.WriteVertexBuffer(mesh, vertexes); BufferHelper.WriteIndexBuffer(mesh, indexes); MeshHelper.GenerateNormalsAndTangents(device, ref mesh, false); return(mesh); }
/// <summary> /// Creates a new <see cref="Mesh"/> representing a textured sphere with spherical mapping. /// </summary> /// <param name="device">The <see cref="Device"/> to create the mesh in</param> /// <param name="radius">The radius of the sphere.</param> /// <param name="slices">The number of vertical slices to divide the sphere into.</param> /// <param name="stacks">The number of horizontal stacks to divide the sphere into.</param> /// <remarks>The sphere is formed like the one created by <see cref="Mesh.CreateSphere"/>.</remarks> public static Mesh Sphere(Device device, float radius, int slices, int stacks) { #region Sanity checks if (device == null) { throw new ArgumentNullException(nameof(device)); } if (slices <= 0) { throw new ArgumentOutOfRangeException(nameof(slices)); } if (stacks <= 0) { throw new ArgumentOutOfRangeException(nameof(stacks)); } #endregion int numVertexes = (slices + 1) * (stacks + 1); int numFaces = slices * stacks * 2; int indexCount = numFaces * 3; var mesh = new Mesh(device, numFaces, numVertexes, MeshFlags.Managed, PositionNormalTextured.Format); #region Build sphere vertexes var vertexes = new PositionNormalTextured[mesh.VertexCount]; int vertIndex = 0; for (int slice = 0; slice <= slices; slice++) { float alphaY = (float)slice / slices * (float)Math.PI * 2.0f; // Angle around Y-axis for (int stack = 0; stack <= stacks; stack++) { if (slice == slices) { vertexes[vertIndex] = vertexes[stack]; } else { var pnt = new PositionNormalTextured(); float alphaZ = ((stack - stacks * 0.5f) / stacks) * (float)Math.PI * 1.0f; // Angle around Z-axis pnt.X = (float)(Math.Cos(alphaY) * radius) * (float)Math.Cos(alphaZ); pnt.Z = (float)(Math.Sin(alphaY) * radius) * (float)Math.Cos(alphaZ); pnt.Y = (float)(Math.Sin(alphaZ) * radius); pnt.Nx = pnt.X / radius; pnt.Ny = pnt.Y / radius; pnt.Nz = pnt.Z / radius; pnt.Tv = 0.5f - (float)(Math.Asin(pnt.Y / radius) / Math.PI); vertexes.SetValue(pnt, vertIndex); } vertexes[vertIndex++].Tu = (float)slice / slices; } } #endregion BufferHelper.WriteVertexBuffer(mesh, vertexes); #region Build index buffer var indexes = new short[indexCount]; int i = 0; for (short x = 0; x < slices; x++) { var leftVertex = (short)((stacks + 1) * x); var rightVertex = (short)(leftVertex + stacks + 1); for (int y = 0; y < stacks; y++) { indexes[i++] = rightVertex; indexes[i++] = leftVertex; indexes[i++] = (short)(leftVertex + 1); indexes[i++] = rightVertex; indexes[i++] = (short)(leftVertex + 1); indexes[i++] = (short)(rightVertex + 1); leftVertex++; rightVertex++; } } #endregion BufferHelper.WriteIndexBuffer(mesh, indexes); return(mesh); }