/// <summary> /// Creates a graphics mesh with the triangle mesh data of the given shape and the given /// diffuse and specular material properties. /// </summary> /// <param name="contentManager">The contentManager manager.</param> /// <param name="graphicsService">The graphics service.</param> /// <param name="submesh">The submesh.</param> /// <param name="diffuse">The diffuse material color.</param> /// <param name="specular">The specular material color.</param> /// <param name="specularPower">The specular power of the material.</param> /// <returns>The graphics mesh.</returns> /// <remarks> /// This method does not set the bounding shape of the mesh. (The default is an infinite shape /// which is not optimal for performance.) /// </remarks> public static Mesh CreateMesh(ContentManager contentManager, IGraphicsService graphicsService, Submesh submesh, Vector3 diffuse, Vector3 specular, float specularPower) { Mesh mesh = new Mesh(); mesh.Submeshes.Add(submesh); // Build material. // We could load a predefined material (*.drmat file) // with the content manager. //var material = contentManager.Load<Material>("MyMaterialName"); // Alternatively, we can load some effects and build the material here: Material material = new Material(); // We need an EffectBinding for each render pass. // The "Default" pass uses a BasicEffectBinding (which is an EffectBinding // for the XNA BasicEffect). // Note: The "Default" pass is not used by the DeferredLightingScreen, so // we could ignore this pass in this sample project. BasicEffectBinding defaultEffectBinding = new BasicEffectBinding(graphicsService, null) { LightingEnabled = true, TextureEnabled = true, VertexColorEnabled = false }; defaultEffectBinding.Set("Texture", graphicsService.GetDefaultTexture2DWhite()); defaultEffectBinding.Set("DiffuseColor", new Vector4((Vector3)diffuse, 1)); defaultEffectBinding.Set("SpecularColor", (Vector3)specular); defaultEffectBinding.Set("SpecularPower", specularPower); material.Add("Default", defaultEffectBinding); // EffectBinding for the "ShadowMap" pass. // Note: EffectBindings which are used in a Material must be marked with // the EffectParameterHint Material. EffectBinding shadowMapEffectBinding = new EffectBinding( graphicsService, contentManager.Load <Effect>("DigitalRune\\Materials\\ShadowMap"), null, EffectParameterHint.Material); material.Add("ShadowMap", shadowMapEffectBinding); // EffectBinding for the "GBuffer" pass. EffectBinding gBufferEffectBinding = new EffectBinding( graphicsService, contentManager.Load <Effect>("DigitalRune\\Materials\\GBuffer"), null, EffectParameterHint.Material); gBufferEffectBinding.Set("SpecularPower", specularPower); material.Add("GBuffer", gBufferEffectBinding); // EffectBinding for the "Material" pass. EffectBinding materialEffectBinding = new EffectBinding( graphicsService, contentManager.Load <Effect>("DigitalRune\\Materials\\Material"), null, EffectParameterHint.Material); materialEffectBinding.Set("DiffuseTexture", graphicsService.GetDefaultTexture2DWhite()); materialEffectBinding.Set("DiffuseColor", (Vector3)diffuse); materialEffectBinding.Set("SpecularColor", (Vector3)specular); material.Add("Material", materialEffectBinding); // Assign this material to the submesh. submesh.SetMaterial(material); return(mesh); }
public static Mesh CreateMesh(IGraphicsService graphicsService, Texture2D texture) { if (graphicsService == null) { throw new ArgumentNullException("graphicsService"); } if (texture == null) { throw new ArgumentNullException("texture"); } List <Vector3> positions = new List <Vector3>(); List <ushort> indices = new List <ushort>(); // Create two rings of vertices around the top and bottom of the cylinder. for (int i = 0; i < CylinderSegments; i++) { float angle = ConstantsF.TwoPi * i / CylinderSegments; float x = (float)Math.Cos(angle) * CylinderSize; float z = (float)Math.Sin(angle) * CylinderSize; positions.Add(new Vector3(x, CylinderSize * 5 / 12, z)); positions.Add(new Vector3(x, -CylinderSize * 5 / 12, z)); } // Create two center vertices, used for closing the top and bottom. positions.Add(new Vector3(0, CylinderSize, 0)); positions.Add(new Vector3(0, -CylinderSize, 0)); // Create the individual triangles that make up our skydome. List <VertexPositionTexture> vertices = new List <VertexPositionTexture>(); ushort index = 0; for (int i = 0; i < CylinderSegments; i++) { int j = (i + 1) % CylinderSegments; // Calculate texture coordinates for this segment of the cylinder. float u1 = (float)i / (float)CylinderSegments; float u2 = (float)(i + 1) / (float)CylinderSegments; // Two triangles form a quad, one side segment of the cylinder. vertices.Add(new VertexPositionTexture(positions[i * 2], new Vector2(u1, TexCoordTop))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[j * 2], new Vector2(u2, TexCoordTop))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[i * 2 + 1], new Vector2(u1, TexCoordBottom))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[j * 2], new Vector2(u2, TexCoordTop))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[j * 2 + 1], new Vector2(u2, TexCoordBottom))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[i * 2 + 1], new Vector2(u1, TexCoordBottom))); indices.Add(index++); // Triangle fanning inward to fill the top above this segment. vertices.Add(new VertexPositionTexture(positions[CylinderSegments * 2], new Vector2(u1, 0))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[j * 2], new Vector2(u2, TexCoordTop))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[i * 2], new Vector2(u1, TexCoordTop))); indices.Add(index++); // Triangle fanning inward to fill the bottom below this segment. vertices.Add(new VertexPositionTexture(positions[CylinderSegments * 2 + 1], new Vector2(u1, 1))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[i * 2 + 1], new Vector2(u1, TexCoordBottom))); indices.Add(index++); vertices.Add(new VertexPositionTexture(positions[j * 2 + 1], new Vector2(u2, TexCoordBottom))); indices.Add(index++); } // Create the vertex buffer. VertexBuffer vertexBuffer = new VertexBuffer( graphicsService.GraphicsDevice, VertexPositionTexture.VertexDeclaration, vertices.Count, BufferUsage. None); vertexBuffer.SetData(vertices.ToArray()); // Create the index buffer. IndexBuffer indexBuffer = new IndexBuffer( graphicsService.GraphicsDevice, IndexElementSize.SixteenBits, indices.Count, BufferUsage.None); indexBuffer.SetData(indices.ToArray()); // Create a submesh, which is a set of primitives which can be rendered in // one draw call. Submesh submesh = new Submesh { PrimitiveCount = indices.Count / 3, PrimitiveType = PrimitiveType.TriangleList, StartIndex = 0, StartVertex = 0, VertexCount = vertices.Count, VertexBuffer = vertexBuffer, IndexBuffer = indexBuffer, }; // Create a mesh (which is collection of submeshes and materials). Mesh mesh = new Mesh { Name = "Sky", BoundingShape = new CylinderShape(CylinderSize, 2 * CylinderSize), }; mesh.Submeshes.Add(submesh); // Create a BasicEffectBinding which wraps the XNA BasicEffect. // An EffectBinding connects an effect with effect parameter values ("effect // parameter binding"). Some of these parameter values are defined here. Others, // like World matrices, light parameters, etc. are automatically updated by // the graphics engine in each frame. BasicEffectBinding effectBinding = new BasicEffectBinding(graphicsService, null) { LightingEnabled = false, TextureEnabled = true, VertexColorEnabled = false }; effectBinding.Set("Texture", texture); effectBinding.Set("SpecularColor", new Vector3(0, 0, 0)); // Create a material, which is a collection of effect bindings - one effect // binding for each "render pass". The sky mesh should be rendered in the // "Sky" render pass. This render pass name is an arbitrary string that is // used in SampleGraphicsScreen.cs. Material material = new Material(); material.Add("Sky", effectBinding); // Assign the material to the submesh. submesh.SetMaterial(material); return(mesh); }