/// <summary> /// Creates a cube with six faces each one pointing in a different direction. /// </summary> /// <param name="device">The device.</param> /// <param name="size">The size.</param> /// <param name="toLeftHanded">if set to <c>true</c> vertices and indices will be transformed to left handed. Default is true.</param> /// <returns>A cube.</returns> public static GeometricPrimitive New(GraphicsDevice device, float size = 1.0f, bool toLeftHanded = false) { var vertices = new SolidVertex[CubeFaceCount * 4]; var indices = new int[CubeFaceCount * 6]; size /= 2.0f; int vertexCount = 0; int indexCount = 0; // Create each face in turn. for (int i = 0; i < CubeFaceCount; i++) { Vector3 normal = faceNormals[i]; // Get two vectors perpendicular both to the face normal and to each other. Vector3 basis = i >= 4 ? Vector3.UnitZ : Vector3.UnitY; Vector3 side1 = Vector3.Cross(normal, basis); Vector3 side2 = Vector3.Cross(normal, side1); // Six indices (two triangles) per face. int vbase = i * 4; indices[indexCount++] = vbase + 2; indices[indexCount++] = vbase + 1; indices[indexCount++] = vbase + 0; indices[indexCount++] = vbase + 3; indices[indexCount++] = vbase + 2; indices[indexCount++] = vbase + 0; // Four vertices per face. vertices[vertexCount++] = new SolidVertex((normal - side1 - side2) * size); vertices[vertexCount++] = new SolidVertex((normal - side1 + side2) * size); vertices[vertexCount++] = new SolidVertex((normal + side1 + side2) * size); vertices[vertexCount++] = new SolidVertex((normal + side1 - side2) * size); } // Create the primitive object. return(new GeometricPrimitive(device, vertices, indices, toLeftHanded) { Name = "Cube" }); }
private Buffer <SolidVertex> GetVertexBufferFromBoundingBox(BoundingBox box) { var p0 = new SolidVertex(new Vector3(box.Minimum.X, box.Minimum.Y, box.Minimum.Z)); var p1 = new SolidVertex(new Vector3(box.Maximum.X, box.Minimum.Y, box.Minimum.Z)); var p2 = new SolidVertex(new Vector3(box.Maximum.X, box.Minimum.Y, box.Maximum.Z)); var p3 = new SolidVertex(new Vector3(box.Minimum.X, box.Minimum.Y, box.Maximum.Z)); var p4 = new SolidVertex(new Vector3(box.Minimum.X, box.Maximum.Y, box.Minimum.Z)); var p5 = new SolidVertex(new Vector3(box.Maximum.X, box.Maximum.Y, box.Minimum.Z)); var p6 = new SolidVertex(new Vector3(box.Maximum.X, box.Maximum.Y, box.Maximum.Z)); var p7 = new SolidVertex(new Vector3(box.Minimum.X, box.Maximum.Y, box.Maximum.Z)); var vertices = new[] { p4, p5, p5, p1, p1, p0, p0, p4, p5, p6, p6, p2, p2, p1, p1, p5, p2, p6, p6, p7, p7, p3, p3, p2, p7, p4, p4, p0, p0, p3, p3, p7, p7, p6, p6, p5, p5, p4, p4, p7, p0, p1, p1, p2, p2, p3, p3, p0 }; return(Buffer.New(_device, vertices, BufferFlags.VertexBuffer, SharpDX.Direct3D11.ResourceUsage.Default)); }
/// <summary> /// Creates a sphere primitive. /// </summary> /// <param name="device">The device.</param> /// <param name="diameter">The diameter.</param> /// <param name="tessellation">The tessellation.</param> /// <param name="toLeftHanded">if set to <c>true</c> vertices and indices will be transformed to left handed. Default is true.</param> /// <returns>A sphere primitive.</returns> /// <exception cref="System.ArgumentOutOfRangeException">tessellation;Must be >= 3</exception> public static GeometricPrimitive New(GraphicsDevice device, float diameter = 1.0f, int tessellation = 16, bool toLeftHanded = false) { if (tessellation < 3) { throw new ArgumentOutOfRangeException(nameof(tessellation), "Must be >= 3"); } int verticalSegments = tessellation; int horizontalSegments = tessellation * 2; var vertices = new SolidVertex[(verticalSegments + 1) * (horizontalSegments + 1)]; var indices = new int[verticalSegments * (horizontalSegments + 1) * 6]; float radius = diameter / 2; int vertexCount = 0; // Create rings of vertices at progressively higher latitudes. for (int i = 0; i <= verticalSegments; i++) { float v = 1.0f - (float)i / verticalSegments; var latitude = (float)(i * Math.PI / verticalSegments - Math.PI / 2.0); var dy = (float)Math.Sin(latitude); var dxz = (float)Math.Cos(latitude); // Create a single ring of vertices at this latitude. for (int j = 0; j <= horizontalSegments; j++) { float u = (float)j / horizontalSegments; var longitude = (float)(j * 2.0 * Math.PI / horizontalSegments); var dx = (float)Math.Sin(longitude); var dz = (float)Math.Cos(longitude); dx *= dxz; dz *= dxz; var normal = new Vector3(dx, dy, dz); var textureCoordinate = new Vector2(u, v); vertices[vertexCount++] = new SolidVertex(normal * radius); } } // Fill the index buffer with triangles joining each pair of latitude rings. int stride = horizontalSegments + 1; int indexCount = 0; for (int i = 0; i < verticalSegments; i++) { for (int j = 0; j <= horizontalSegments; j++) { int nextI = i + 1; int nextJ = (j + 1) % stride; indices[indexCount++] = i * stride + nextJ; indices[indexCount++] = nextI * stride + j; indices[indexCount++] = i * stride + j; indices[indexCount++] = nextI * stride + nextJ; indices[indexCount++] = nextI * stride + j; indices[indexCount++] = i * stride + nextJ; } } // Create the primitive object. return(new GeometricPrimitive(device, vertices, indices, toLeftHanded) { Name = "Sphere" }); }
/// <summary> /// Creates a Plane primitive on the X/Y plane with a normal equal to -<see cref="Vector3.UnitZ" />. /// </summary> /// <param name="device">The device.</param> /// <param name="sizeX">The size X.</param> /// <param name="sizeY">The size Y.</param> /// <param name="tessellation">The tessellation, as the number of quads per axis.</param> /// <param name="uvFactor">The uv factor.</param> /// <param name="toLeftHanded">if set to <c>true</c> vertices and indices will be transformed to left handed. Default is true.</param> /// <returns>A Plane primitive.</returns> /// <exception cref="System.ArgumentOutOfRangeException">tessellation;tessellation must be > 0</exception> public static GeometricPrimitive New(GraphicsDevice device, float size, int tessellation, bool toLeftHanded = false) { if (tessellation < 1) { throw new ArgumentOutOfRangeException(nameof(tessellation), "tessellation must be > 0"); } int start = (int)(-size * 1024.0f); int end = (int)(size * 1024.0f); int step = (int)(1024.0f / tessellation); var vertices = new List <SolidVertex>(); var indices = new List <int>(); int lastIndex = 0; for (int x = start; x <= end; x += step) { var color = Vector4.One; if (x % 1024 != 0) { color = new Vector4(0.75f, 0.75f, 0.75f, 1.0f); } if (x == 0) { color = new Vector4(0.0f, 0.0f, 1.0f, 1.0f); } var v1 = new SolidVertex(); v1.Position = new Vector3(x, 0.0f, x == 0 ? -32768.0f : start); v1.Color = color; var v2 = new SolidVertex(); v2.Position = new Vector3(x, 0.0f, x == 0 ? 32768.0f : end); v2.Color = color; vertices.Add(v1); vertices.Add(v2); indices.Add(lastIndex++); indices.Add(lastIndex++); } for (int z = start; z <= end; z += step) { var color = Vector4.One; if (z % 1024 != 0) { color = new Vector4(0.75f, 0.75f, 0.75f, 1.0f); } if (z == 0) { color = new Vector4(0.0f, 0.0f, 1.0f, 1.0f); } var v1 = new SolidVertex(); v1.Position = new Vector3(z == 0 ? -32768.0f : start, 0.0f, z); v1.Color = color; var v2 = new SolidVertex(); v2.Position = new Vector3(z == 0 ? 32768.0f : end, 0.0f, z); v2.Color = color; vertices.Add(v1); vertices.Add(v2); indices.Add(lastIndex++); indices.Add(lastIndex++); } // Add a final Y axis line var vy1 = new SolidVertex(); vy1.Position = new Vector3(0.0f, -32768.0f, 0.0f); vy1.Color = new Vector4(0.0f, 0.0f, 1.0f, 1.0f); var vy2 = new SolidVertex(); vy2.Position = new Vector3(0.0f, 32768.0f, 0.0f); vy2.Color = new Vector4(0.0f, 0.0f, 1.0f, 1.0f); vertices.Add(vy1); vertices.Add(vy2); indices.Add(lastIndex++); indices.Add(lastIndex++); // Create the primitive object. return(new GeometricPrimitive(device, vertices.ToArray(), indices.ToArray(), toLeftHanded) { Name = "Grid" }); }
protected override void OnDraw() { // To make sure things are in a defined state for legacy rendering... ((TombLib.Rendering.DirectX11.Dx11RenderingSwapChain)SwapChain).BindForce(); ((TombLib.Rendering.DirectX11.Dx11RenderingDevice)Device).ResetState(); _device.SetDepthStencilState(_device.DepthStencilStates.Default); _device.SetRasterizerState(_device.RasterizerStates.CullBack); _device.SetBlendState(_device.BlendStates.Opaque); Matrix4x4 viewProjection = Camera.GetViewProjectionMatrix(ClientSize.Width, ClientSize.Height); Effect solidEffect = _deviceManager.___LegacyEffects["Solid"]; if (Static != null) { var model = _wadRenderer.GetStatic(Static); var effect = _deviceManager.___LegacyEffects["StaticModel"]; var world = GizmoTransform; effect.Parameters["ModelViewProjection"].SetValue((world * viewProjection).ToSharpDX()); effect.Parameters["Color"].SetValue(Vector4.One); effect.Parameters["Texture"].SetResource(_wadRenderer.Texture); effect.Parameters["TextureSampler"].SetResource(_device.SamplerStates.Default); for (int i = 0; i < model.Meshes.Count; i++) { var mesh = model.Meshes[i]; _device.SetVertexBuffer(0, mesh.VertexBuffer); _device.SetIndexBuffer(mesh.IndexBuffer, true); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, mesh.VertexBuffer)); effect.Parameters["ModelViewProjection"].SetValue((world * viewProjection).ToSharpDX()); effect.Techniques[0].Passes[0].Apply(); foreach (var submesh in mesh.Submeshes) { _device.Draw(PrimitiveType.TriangleList, submesh.Value.NumIndices, submesh.Value.BaseIndex); } //foreach (var submesh in mesh.Submeshes) // _device.DrawIndexed(PrimitiveType.TriangleList, submesh.Value.NumIndices, submesh.Value.MeshBaseIndex); } _device.SetRasterizerState(_rasterizerWireframe); // Draw boxes if (DrawVisibilityBox || DrawCollisionBox) { if (DrawVisibilityBox) { _vertexBufferVisibility?.Dispose(); _vertexBufferVisibility = GetVertexBufferFromBoundingBox(Static.VisibilityBox); _device.SetVertexBuffer(_vertexBufferVisibility); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _vertexBufferVisibility)); _device.SetIndexBuffer(null, false); solidEffect.Parameters["ModelViewProjection"].SetValue(viewProjection.ToSharpDX()); solidEffect.Parameters["Color"].SetValue(new Vector4(0.0f, 1.0f, 0.0f, 1.0f)); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.Draw(PrimitiveType.LineList, _vertexBufferVisibility.ElementCount); } if (DrawCollisionBox) { _vertexBufferCollision?.Dispose(); _vertexBufferCollision = GetVertexBufferFromBoundingBox(Static.CollisionBox); _device.SetVertexBuffer(_vertexBufferCollision); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _vertexBufferCollision)); _device.SetIndexBuffer(null, false); solidEffect.Parameters["ModelViewProjection"].SetValue(viewProjection.ToSharpDX()); solidEffect.Parameters["Color"].SetValue(new Vector4(1.0f, 0.0f, 0.0f, 1.0f)); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.Draw(PrimitiveType.LineList, _vertexBufferCollision.ElementCount); } } // Draw normals if (DrawNormals) { var lines = new List <SolidVertex>(); for (int i = 0; i < Static.Mesh.VerticesNormals.Count; i++) { var p = Vector3.Transform(Static.Mesh.VerticesPositions[i], world); var n = Vector3.TransformNormal(Static.Mesh.VerticesNormals[i] / Static.Mesh.VerticesNormals[i].Length(), world); var v = new SolidVertex(); v.Position = p; v.Color = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); lines.Add(v); v = new SolidVertex(); v.Position = p + n * 256.0f; v.Color = new Vector4(1.0f, 1.0f, 1.0f, 1.0f); lines.Add(v); } Buffer <SolidVertex> bufferLines = Buffer.New(_device, lines.ToArray(), BufferFlags.VertexBuffer, SharpDX.Direct3D11.ResourceUsage.Default); _device.SetVertexBuffer(bufferLines); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, bufferLines)); _device.SetIndexBuffer(null, false); solidEffect.Parameters["ModelViewProjection"].SetValue(viewProjection.ToSharpDX()); solidEffect.Parameters["Color"].SetValue(new Vector4(1.0f, 1.0f, 1.0f, 1.0f)); solidEffect.CurrentTechnique.Passes[0].Apply(); _device.Draw(PrimitiveType.LineList, bufferLines.ElementCount); } } if (DrawGrid) { _device.SetRasterizerState(_rasterizerWireframe); // Draw the grid _device.SetVertexBuffer(0, _plane.VertexBuffer); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _plane.VertexBuffer)); _device.SetIndexBuffer(_plane.IndexBuffer, true); solidEffect.Parameters["ModelViewProjection"].SetValue(viewProjection.ToSharpDX()); solidEffect.Parameters["Color"].SetValue(Vector4.One); solidEffect.Techniques[0].Passes[0].Apply(); _device.Draw(PrimitiveType.LineList, _plane.VertexBuffer.ElementCount); } if (DrawLights) { _device.SetRasterizerState(_rasterizerWireframe); foreach (var light in Static.Lights) { // Draw the little sphere _device.SetVertexBuffer(0, _littleSphere.VertexBuffer); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _littleSphere.VertexBuffer)); _device.SetIndexBuffer(_littleSphere.IndexBuffer, false); var world = Matrix4x4.CreateTranslation(light.Position); solidEffect.Parameters["ModelViewProjection"].SetValue((world * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(new Vector4(1.0f, 1.0f, 0.0f, 1.0f)); solidEffect.Techniques[0].Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _littleSphere.IndexBuffer.ElementCount); if (SelectedLight == light) { _device.SetVertexBuffer(0, _sphere.VertexBuffer); _device.SetVertexInputLayout(VertexInputLayout.FromBuffer(0, _sphere.VertexBuffer)); _device.SetIndexBuffer(_sphere.IndexBuffer, false); world = Matrix4x4.CreateScale(light.Radius * 2.0f) * Matrix4x4.CreateTranslation(light.Position); solidEffect.Parameters["ModelViewProjection"].SetValue((world * viewProjection).ToSharpDX()); solidEffect.Parameters["Color"].SetValue(new Vector4(0.0f, 1.0f, 0.0f, 1.0f)); solidEffect.Techniques[0].Passes[0].Apply(); _device.DrawIndexed(PrimitiveType.TriangleList, _sphere.IndexBuffer.ElementCount); } } _device.SetRasterizerState(_device.RasterizerStates.CullBack); } if (DrawGizmo) { // Draw the gizmo SwapChain.ClearDepth(); _gizmo.Draw(viewProjection); } if (SelectedLight != null) { // Draw the gizmo of selected light SwapChain.ClearDepth(); _gizmoLight.Draw(viewProjection); } // Draw debug strings ((TombLib.Rendering.DirectX11.Dx11RenderingDevice)Device).ResetState(); // To make sure SharpDx.Toolkit didn't change settings. SwapChain.RenderText(new Text { Font = _fontDefault, PixelPos = new Vector2(5, 5), Alignment = new Vector2(0, 0), String = "Position: " + StaticPosition + "\nRotation: " + StaticRotation.X * (180 / Math.PI) + "\nScale: " + StaticScale }); }
/// <summary> /// Creates a sphere primitive. /// </summary> /// <param name="device">The device.</param> /// <param name="diameter">The diameter.</param> /// <param name="tessellation">The tessellation.</param> /// <param name="toLeftHanded">if set to <c>true</c> vertices and indices will be transformed to left handed. Default is true.</param> /// <returns>A sphere primitive.</returns> /// <exception cref="System.ArgumentOutOfRangeException">tessellation;Must be >= 3</exception> public static GeometricPrimitive New(GraphicsDevice device, float diameter = 1.0f, float length = 1.0f, int tessellation = 18, bool toLeftHanded = false) { if (tessellation < 3) { throw new ArgumentOutOfRangeException(nameof(tessellation), "Must be >= 3"); } int verticalSegments = tessellation; int horizontalSegments = tessellation * 2; var vertices = new SolidVertex[(verticalSegments + 1) * (horizontalSegments + 1)]; var indices = new int[verticalSegments * (horizontalSegments + 1) * 6]; float radius = diameter / 2; // Vertex of the cone float angle = (float)(2 * Math.PI / tessellation); List <SolidVertex> tempVertices = new List <SolidVertex>(); List <int> tempIndices = new List <int>(); for (int i = 0; i < verticalSegments; i++) { float x = radius * (float)Math.Sin(i * angle); float y = radius * (float)Math.Cos(i * angle); float z = length; tempVertices.Add(new SolidVertex(new Vector3(x, y, z))); } tempVertices.Add(new SolidVertex(new Vector3(0.0f, 0.0f, 0.0f))); for (int i = 0; i < tessellation; i++) { int first = i; int last = i == tessellation - 1 ? 0 : i + 1; int cone = tempVertices.Count - 1; tempIndices.Add(cone); tempIndices.Add(first); tempIndices.Add(last); } // Create rings of vertices at progressively higher latitudes. /* for (int i = 0; i <= verticalSegments; i++) * { * float v = 1.0f - (float)i / verticalSegments; * * var latitude = (float)((i * Math.PI / verticalSegments) - Math.PI / 2.0); * var dy = (float)Math.Sin(latitude); * var dxz = (float)Math.Cos(latitude); * * // Create a single ring of vertices at this latitude. * for (int j = 0; j <= horizontalSegments; j++) * { * float u = (float)j / horizontalSegments; * * var longitude = (float)(j * 2.0 * Math.PI / horizontalSegments); * var dx = (float)Math.Sin(longitude); * var dz = (float)Math.Cos(longitude); * * dx *= dxz; * dz *= dxz; * * var normal = new Vector3(dx, dy, dz); * var textureCoordinate = new Vector2(u, v); * * SolidVertex vertex = new TombLib.LevelData.SolidVertex(); * vertex.Position = new Vector4(normal * radius, 1); * vertex.Normal = normal; * vertex.UV = textureCoordinate; * * vertices[vertexCount++] = vertex; * } * } * * // Fill the index buffer with triangles joining each pair of latitude rings. * int stride = horizontalSegments + 1; * * int indexCount = 0; * for (int i = 0; i < verticalSegments; i++) * { * for (int j = 0; j <= horizontalSegments; j++) * { * int nextI = i + 1; * int nextJ = (j + 1) % stride; * * indices[indexCount++] = (i * stride + nextJ); * indices[indexCount++] = (nextI * stride + j); * indices[indexCount++] = (i * stride + j); * * indices[indexCount++] = (nextI * stride + nextJ); * indices[indexCount++] = (nextI * stride + j); * indices[indexCount++] = (i * stride + nextJ); * } * }*/ vertices = tempVertices.ToArray(); indices = tempIndices.ToArray(); // Create the primitive object. return(new GeometricPrimitive(device, vertices, indices, toLeftHanded) { Name = "Sphere" }); }