示例#1
0
        public override void Start()
        {
            base.Start();
            float size = Main.instance.RandomMinMax(0.003666f, 0.00666f);
            // VertexPositionNormalTexture is the layout that the engine uses in the shaders
            var vBuffer = Stride.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[]
            {
                new VertexPositionNormalTexture(new Vector3(0, -size, 0), new Vector3(0, 1, 1), new Vector2(0, 0)), //Top Left.
                new VertexPositionNormalTexture(new Vector3(0, size, 0), new Vector3(0, 1, 1), new Vector2(0, 0))   //Bottom right.
            });

            MeshDraw meshDraw = new MeshDraw
            {
                PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line.
                VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) },
                DrawCount     = vBuffer.ElementCount
            };

            Mesh mesh = new Mesh();

            mesh.Draw = meshDraw;

            Model model = new Model();

            model.Add(mesh);
            lineMesh = new ModelComponent(model);
            line     = new Entity();
            line.Add(lineMesh);
            Entity.AddChild(line);
            Destroy();
        }
示例#2
0
        public static Mesh LoadMesh(SharpGLTF.Schema2.MeshPrimitive mesh, GraphicsDevice device)
        {
            var draw = new MeshDraw
            {
                PrimitiveType = ConvertPrimitiveType(mesh.DrawPrimitiveType),
                IndexBuffer   = ConvertIndexBufferBinding(mesh, device),
                VertexBuffers = ConvertVertexBufferBinding(mesh, device),
                DrawCount     = GetDrawCount(mesh)
            };



            var result = new Mesh(draw, new ParameterCollection())
            {
                Skinning      = ConvertInverseBindMatrices(mesh.LogicalParent.LogicalParent),
                Name          = mesh.LogicalParent.Name,
                MaterialIndex = mesh.LogicalParent.LogicalParent.LogicalMaterials.ToList().IndexOf(mesh.Material)
            };


            //TODO : Add parameter collection only after checking if it has
            result.Parameters.Set(MaterialKeys.HasSkinningPosition, true);
            result.Parameters.Set(MaterialKeys.HasSkinningNormal, true);
            return(result);
        }
        public void Build(RenderDrawContext context)
        {
            if (Mesh == null && TryGetHeightMapImageData(context.CommandList, out var data))
            {
                Data               = new GeometryBuilder(data).BuildTerrainData(Size, MaxHeight, UvScale);
                MeshBoundingBox    = Utils.FromPoints(Data.Vertices);
                MeshBoundingSphere = BoundingSphere.FromBox(MeshBoundingBox);
                BoundingBox        = new BoundingBoxExt(MeshBoundingBox);

                var vertexBuffer        = Buffer.Vertex.New(context.GraphicsDevice, Data.Vertices, GraphicsResourceUsage.Dynamic);
                var indexBuffer         = Buffer.Index.New(context.GraphicsDevice, Data.Indices);
                var vertexBufferBinding = new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount);
                var indexBufferBinding  = new IndexBufferBinding(indexBuffer, true, indexBuffer.ElementCount);

                MeshDraw = new MeshDraw
                {
                    StartLocation = 0,
                    PrimitiveType = PrimitiveType.TriangleList,
                    VertexBuffers = new[] { vertexBufferBinding },
                    IndexBuffer   = indexBufferBinding,
                    DrawCount     = indexBuffer.ElementCount
                };

                Mesh = new Mesh(MeshDraw, new ParameterCollection());
            }
        }
示例#4
0
            public void Build(CommandList commandList, CameraParameters parameters)
            {
                var indices = new []
                {
                    0, 1,
                    1, 2,
                    2, 3,
                    3, 0,

                    4, 5,
                    5, 6,
                    6, 7,
                    7, 4,

                    0, 4,
                    1, 5,
                    2, 6,
                    3, 7
                };

                vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[8], GraphicsResourceUsage.Dynamic);
                RebuildVertexBuffer(commandList, parameters);

                MeshDraw = new MeshDraw
                {
                    PrimitiveType = PrimitiveType.LineList,
                    DrawCount     = indices.Length,
                    IndexBuffer   = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length),
                    VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) },
                };
            }
        /// <summary>
        /// Generates the index buffer with dominant edge and vertex information.
        /// Each triangle gets its indices expanded to 12 control points, with 0 to 2 being original triangle,
        /// 3 to 8 being dominant edges and 9 to 11 being dominant vertices.
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        public unsafe static void GenerateIndexBufferAEN(this MeshDraw meshData)
        {
            // For now, require a MeshData with only one vertex buffer and one index buffer
            if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null)
            {
                throw new NotImplementedException();
            }

            // Generate the new indices
            var newIndices = GenerateIndexBufferAEN(meshData.IndexBuffer, meshData.VertexBuffers[0]);

            // copy them into a byte[]
            var triangleCount   = meshData.IndexBuffer.Count / 3;
            var indexBufferData = new byte[triangleCount * 12 * Utilities.SizeOf <int>()];

            fixed(int *indexDataStart = &newIndices[0])
            fixed(byte *indexBufferDataStart = &indexBufferData[0])
            {
                Utilities.CopyMemory((IntPtr)indexBufferDataStart, (IntPtr)indexDataStart, indexBufferData.Length);
            }

            meshData.IndexBuffer   = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), true, triangleCount * 12);
            meshData.DrawCount     = meshData.IndexBuffer.Count;
            meshData.PrimitiveType = PrimitiveType.PatchList.ControlPointCount(12);
        }
示例#6
0
        /// <summary>
        /// Generates the tangents and binormals for this mesh data.
        /// Tangents and bitangents will be encoded as float4:
        /// float3 for tangent and an additional float for handedness (1 or -1),
        /// so that bitangent can be reconstructed.
        /// More info at http://www.terathon.com/code/tangent.html
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        public static unsafe void GenerateTangentBinormal(this MeshDraw meshData)
        {
            if (!meshData.IsSimple())
            {
                throw new ArgumentException("meshData is not simple.");
            }

            if (meshData.PrimitiveType != PrimitiveType.TriangleList &&
                meshData.PrimitiveType != PrimitiveType.TriangleListWithAdjacency)
            {
                throw new NotImplementedException();
            }

            var oldVertexBufferBinding = meshData.VertexBuffers[0];
            var indexBufferBinding     = meshData.IndexBuffer;
            var indexData = indexBufferBinding != null?indexBufferBinding.Buffer.GetSerializationData().Content : null;

            var oldVertexStride = oldVertexBufferBinding.Declaration.VertexStride;
            var bufferData      = oldVertexBufferBinding.Buffer.GetSerializationData().Content;

            fixed(byte *indexBufferStart = indexData)
            fixed(byte *oldBuffer = bufferData)
            {
                var result = VertexHelper.GenerateTangentBinormal(oldVertexBufferBinding.Declaration, (IntPtr)oldBuffer, oldVertexBufferBinding.Count, oldVertexBufferBinding.Offset, oldVertexBufferBinding.Stride, (IntPtr)indexBufferStart, indexBufferBinding != null && indexBufferBinding.Is32Bit, indexBufferBinding != null ? indexBufferBinding.Count : 0);

                // Replace new vertex buffer binding
                meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, result.VertexBuffer).ToSerializableVersion(), result.Layout, oldVertexBufferBinding.Count);
            }
        }
示例#7
0
        /// <summary>
        /// Expand vertices using index buffer (if existing), and remove it.
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        public static unsafe void RemoveIndexBuffer(this MeshDraw meshData)
        {
            if (meshData.IndexBuffer == null)
            {
                return;
            }

            // For now, require a MeshData with only one vertex buffer and a 32 bit full index buffer
            if (meshData.VertexBuffers.Length != 1 || !meshData.IndexBuffer.Is32Bit ||
                meshData.StartLocation != 0 || meshData.DrawCount != meshData.IndexBuffer.Count)
            {
                throw new NotImplementedException();
            }

            var vertexBuffer = meshData.VertexBuffers[0];
            var indexBuffer  = meshData.IndexBuffer;
            var stride       = vertexBuffer.Stride;
            var newVertices  = new byte[stride * indexBuffer.Count];

            fixed(byte *newVerticesStart = newVertices)
            fixed(byte *indexBufferStart  = &indexBuffer.Buffer.GetDataSafe()[indexBuffer.Offset])
            fixed(byte *vertexBufferStart = &vertexBuffer.Buffer.GetDataSafe()[indexBuffer.Offset])
            {
                for (int i = 0; i < indexBuffer.Count; ++i)
                {
                    var index = ((int *)indexBufferStart)[i];
                    Utilities.CopyMemory((IntPtr)newVerticesStart + i * stride, (IntPtr)vertexBufferStart + index * stride, stride);
                }
            }

            meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, newVertices).ToSerializableVersion(), vertexBuffer.Declaration, indexBuffer.Count);
            meshData.IndexBuffer      = null;
        }
示例#8
0
            public void Build(CommandList commandList, LightSpot lightSpot)
            {
                int[] indices;

                if (lightSpot.ProjectiveTexture != null)    // If no projection texture has been supplied, we render the regular cone:
                {
                    indices      = BuildRectangleIndexBuffer();
                    vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[9], GraphicsResourceUsage.Dynamic);
                    RebuildRectangleVertexBuffer(commandList, lightSpot);
                }
                else    // If a projection texture has been supplied, we render a rectangular frustum instead:
                {
                    indices      = BuildConeIndexBuffer();
                    vertexBuffer = Buffer.Vertex.New(graphicsDevice, new VertexPositionNormalTexture[4 * Tesselation + 1], GraphicsResourceUsage.Dynamic);
                    RebuildConeVertexBuffer(commandList, lightSpot);
                }

                MeshDraw = new MeshDraw
                {
                    PrimitiveType = PrimitiveType.LineList,
                    DrawCount     = indices.Length,
                    IndexBuffer   = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length),
                    VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) },
                };
            }
示例#9
0
        private void m_RockTwo()
        {
            // VertexPositionNormalTexture is the layout that the engine uses in the shaders
            var vBuffer = Xenko.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[]
            {
                new VertexPositionNormalTexture(new Vector3(2.9f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(1.4f, 2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(0.0f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(-1.5f, 2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(-2.9f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(-2.2f, 0.0f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(-2.9f, -1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(-0.7f, -2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(1.4f, -2.9f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(2.9f, -1.4f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),
                new VertexPositionNormalTexture(new Vector3(2.9f, 1.5f, 0), new Vector3(0, 1, 1), new Vector2(0, 0))
            });

            MeshDraw meshDraw = new MeshDraw
            {
                PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line.
                VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) },
                DrawCount     = vBuffer.ElementCount
            };

            Mesh mesh = new Mesh();

            mesh.Draw = meshDraw;

            Model model = new Model();

            model.Add(mesh);
            m_RockMesh = new ModelComponent(model);
        }
示例#10
0
        public override void Start()
        {
            // VertexPositionNormalTexture is the layout that the engine uses in the shaders
            var vBuffer = Xenko.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[]
            {
                new VertexPositionNormalTexture(new Vector3(0.015f, 0.015f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)),  //Top Left.
                new VertexPositionNormalTexture(new Vector3(-0.015f, -0.015f, 0), new Vector3(0, 1, 1), new Vector2(0, 0)) //Bottom right.
            });

            MeshDraw meshDraw = new MeshDraw
            {
                PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line.
                VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) },
                DrawCount     = vBuffer.ElementCount
            };

            Mesh mesh = new Mesh();

            mesh.Draw = meshDraw;

            Model model = new Model();

            model.Add(mesh);
            m_DotMesh = new ModelComponent(model);

            m_Dot = new Entity();
            m_Dot.Add(m_DotMesh);
            this.Entity.AddChild(m_Dot);
            Destroy();
        }
示例#11
0
        /// <summary>
        /// Reverses the winding order of an index buffer. Assumes it is stored in <see cref="PrimitiveType.TriangleList"/> format.
        /// Works on both 32 and 16 bit indices.
        /// </summary>
        /// <param name="outBytes">Output of the operation, the indices matching the reversed winding order</param>
        public static unsafe bool GetReversedWindingOrder(this MeshDraw meshData, out byte[] outBytes)
        {
            // Initially set output to null
            outBytes = null;

            // For now, require a MeshData with only one vertex buffer and no index buffer
            if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null)
            {
                return(false);
            }

            // Need to be triangle list format
            if (meshData.PrimitiveType != PrimitiveType.TriangleList)
            {
                return(false);
            }

            // Create new index buffer
            var indexCount = meshData.IndexBuffer.Count;

            outBytes = new byte[indexCount * (meshData.IndexBuffer.Is32Bit ? sizeof(uint) : sizeof(ushort))];
            fixed(byte *oldIndexBufferDataStart = &meshData.IndexBuffer.Buffer.GetDataSafe()[0])
            fixed(byte *indexBufferDataStart = &outBytes[0])
            {
                if (meshData.IndexBuffer.Is32Bit)
                {
                    var oldIndexBufferDataPtr = (uint *)oldIndexBufferDataStart;
                    var indexBufferDataPtr    = (uint *)indexBufferDataStart;

                    for (int i = 0; i < indexCount; i += 3)
                    {
                        // Swap second and third indices
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[0];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[2];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[1];

                        oldIndexBufferDataPtr += 3;
                    }
                }
                else
                {
                    var oldIndexBufferDataPtr = (ushort *)oldIndexBufferDataStart;
                    var indexBufferDataPtr    = (ushort *)indexBufferDataStart;

                    for (int i = 0; i < indexCount; i += 3)
                    {
                        // Swap second and third indices
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[0];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[2];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[1];

                        oldIndexBufferDataPtr += 3;
                    }
                }
            }

            return(true);
        }
示例#12
0
        /// <summary>
        /// Reverses the winding order of an index buffer. Assumes it is stored in <see cref="PrimitiveType.TriangleList"/> format.
        /// Works on both 32 and 16 bit indices.
        /// </summary>
        /// <param name="vertexBufferBinding">The vertex buffer binding.</param>
        /// <exception cref="System.NotImplementedException"></exception>
        public unsafe static bool ReverseWindingOrder(this MeshDraw meshData)
        {
            // For now, require a MeshData with only one vertex buffer and no index buffer
            if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer == null)
            {
                return(false);
            }

            // Need to be triangle list format
            if (meshData.PrimitiveType != PrimitiveType.TriangleList)
            {
                return(false);
            }

            // Create new index buffer
            var indexCount      = meshData.IndexBuffer.Count;
            var indexBufferData = new byte[indexCount * (meshData.IndexBuffer.Is32Bit ? sizeof(uint) : sizeof(ushort))];

            fixed(byte *oldIndexBufferDataStart = &meshData.IndexBuffer.Buffer.GetDataSafe()[0])
            fixed(byte *indexBufferDataStart = &indexBufferData[0])
            {
                if (meshData.IndexBuffer.Is32Bit)
                {
                    var oldIndexBufferDataPtr = (uint *)oldIndexBufferDataStart;
                    var indexBufferDataPtr    = (uint *)indexBufferDataStart;

                    for (int i = 0; i < indexCount; i += 3)
                    {
                        // Swap second and third indices
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[0];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[2];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[1];

                        oldIndexBufferDataPtr += 3;
                    }
                }
                else
                {
                    var oldIndexBufferDataPtr = (ushort *)oldIndexBufferDataStart;
                    var indexBufferDataPtr    = (ushort *)indexBufferDataStart;

                    for (int i = 0; i < indexCount; i += 3)
                    {
                        // Swap second and third indices
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[0];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[2];
                        *indexBufferDataPtr++ = oldIndexBufferDataPtr[1];

                        oldIndexBufferDataPtr += 3;
                    }
                }

                meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), meshData.IndexBuffer.Is32Bit, indexCount);
            }

            return(true);
        }
示例#13
0
        /// <summary>
        /// Reverses the winding order of an index buffer. Assumes it is stored in <see cref="PrimitiveType.TriangleList"/> format.
        /// Works on both 32 and 16 bit indices.
        /// </summary>
        public static bool ReverseWindingOrder(this MeshDraw meshData)
        {
            byte[] newIndexBuffer;
            if (!GetReversedWindingOrder(meshData, out newIndexBuffer))
            {
                return(false);
            }

            meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, newIndexBuffer).ToSerializableVersion(), meshData.IndexBuffer.Is32Bit, meshData.IndexBuffer.Count);
            return(true);
        }
示例#14
0
            public void Build()
            {
                var indices  = new int[2 * Tesselation * 3];
                var vertices = new VertexPositionNormalTexture[(Tesselation + 1) * 3];

                int indexCount  = 0;
                int vertexCount = 0;

                // the two rings
                for (int j = 0; j < 3; j++)
                {
                    var rotation = Matrix.Identity;
                    if (j == 1)
                    {
                        rotation = Matrix.RotationX(MathF.PI / 2);
                    }
                    else if (j == 2)
                    {
                        rotation = Matrix.RotationY(MathF.PI / 2);
                    }

                    for (int i = 0; i <= Tesselation; i++)
                    {
                        var longitude = (float)(i * 2.0 * Math.PI / Tesselation);
                        var dx        = MathF.Cos(longitude);
                        var dy        = MathF.Sin(longitude);

                        var normal = new Vector3(dx, dy, 0);
                        Vector3.TransformNormal(ref normal, ref rotation, out normal);

                        if (i < Tesselation)
                        {
                            indices[indexCount++] = vertexCount;
                            indices[indexCount++] = vertexCount + 1;
                        }

                        vertices[vertexCount++] = new VertexPositionNormalTexture(normal, normal, new Vector2(0));
                    }
                }

                vertexBuffer = Buffer.Vertex.New(graphicsDevice, vertices);
                MeshDraw     = new MeshDraw
                {
                    PrimitiveType = PrimitiveType.LineList,
                    DrawCount     = indices.Length,
                    IndexBuffer   = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length),
                    VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) },
                };
            }
        /// <summary>
        /// Disposes all GPU buffers of a <see cref="MeshDraw"/>. Make sure it isn't used by the engine before calling this method.
        /// </summary>
        /// <param name="meshDraw">The mesh draw.</param>
        private static void DisposeBuffers(this MeshDraw meshDraw)
        {
            if (meshDraw != null)
            {
                meshDraw.IndexBuffer?.Buffer?.Dispose();

                if (meshDraw.VertexBuffers != null)
                {
                    foreach (var vb in meshDraw.VertexBuffers)
                    {
                        vb.Buffer?.Dispose();
                    }
                }
            }
        }
示例#16
0
        public static MeshDraw ToMeshDraw(this MeshDraw primitive)
        {
            var vertexBufferBinding = new VertexBufferBinding(primitive.VertexBuffers[0].Buffer, new VertexPositionNormalTexture().GetLayout(), primitive.VertexBuffers[0].Count);
            var indexBufferBinding  = new IndexBufferBinding(primitive.IndexBuffer.Buffer, primitive.IndexBuffer.Is32Bit, primitive.IndexBuffer.Buffer.ElementCount);
            var data = new MeshDraw
            {
                StartLocation = 0,
                PrimitiveType = PrimitiveType.TriangleList,
                VertexBuffers = new[] { vertexBufferBinding },
                IndexBuffer   = indexBufferBinding,
                DrawCount     = primitive.IndexBuffer.Buffer.ElementCount,
            };

            return(data);
        }
示例#17
0
        public static MeshDraw ToMeshDraw <T>(this GeometricPrimitive <T> primitive) where T : struct, IVertex
        {
            var vertexBufferBinding = new VertexBufferBinding(primitive.VertexBuffer, new T().GetLayout(), primitive.VertexBuffer.ElementCount);
            var indexBufferBinding  = new IndexBufferBinding(primitive.IndexBuffer, primitive.IsIndex32Bits, primitive.IndexBuffer.ElementCount);
            var data = new MeshDraw
            {
                StartLocation = 0,
                PrimitiveType = PrimitiveType.TriangleList,
                VertexBuffers = new[] { vertexBufferBinding },
                IndexBuffer   = indexBufferBinding,
                DrawCount     = primitive.IndexBuffer.ElementCount,
            };

            return(data);
        }
示例#18
0
            private MeshDraw CreateTileMeshDraw(GraphicsDevice device, VertexPositionNormalColor[] vertices, ushort[] indices)
            {
                var vertexBuffer = Buffer.Vertex.New(device, vertices, GraphicsResourceUsage.Dynamic).RecreateWith(vertices);
                var indexBuffer  = Buffer.Index.New(device, indices).RecreateWith(indices);

                var meshDraw = new MeshDraw
                {
                    PrimitiveType = PrimitiveType.TriangleList,
                    VertexBuffers = new VertexBufferBinding[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalColor.Layout, vertexBuffer.ElementCount) },
                    IndexBuffer   = new IndexBufferBinding(indexBuffer, false, indexBuffer.ElementCount),
                    StartLocation = 0,
                    DrawCount     = indexBuffer.ElementCount,
                };

                return(meshDraw);
            }
示例#19
0
        /// <summary>
        /// Creates an Entity that contains our dynamic Vertex and Index buffers.
        /// This Entity will be rendered by the model renderer.
        /// </summary>
        /// <param name="verticesCount"></param>
        /// <param name="indicesCount"></param>
        private void CreateTerrainModelEntity(int verticesCount, int indicesCount)
        {
            // Compute sizes
            var vertexDeclaration = VertexNormalTexture.VertexDeclaration;
            var vertexBufferSize  = verticesCount * vertexDeclaration.CalculateSize();
            var indexBufferSize   = indicesCount * sizeof(int);

            // Create Vertex and Index buffers
            terrainVertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertexBufferSize, GraphicsResourceUsage.Dynamic);
            terrainIndexBuffer  = Buffer.New(GraphicsDevice, indexBufferSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic);

            // Prepare mesh and entity
            var meshDraw = new MeshDraw
            {
                PrimitiveType = PrimitiveType.TriangleStrip,
                VertexBuffers = new[] { new VertexBufferBinding(terrainVertexBuffer, vertexDeclaration, verticesCount) },
                IndexBuffer   = new IndexBufferBinding(terrainIndexBuffer, true, indicesCount),
            };

//            var effect1 = EffectSystem.LoadEffect("SimpleTerrainEffectMain").WaitForResult();
//            var effect2 = EffectSystem.LoadEffect("VertexTextureTerrain");
            var effectMaterial = LoadAsset <Material>("mt_rock");

            Texture tex0 = (Texture)effectMaterial.Parameters[MaterialKeys.DiffuseMap]; // rock
            Texture tex1 = (Texture)effectMaterial.Parameters[DiffuseMap1];             // grass
            Texture tex2 = (Texture)effectMaterial.Parameters[DiffuseMap2];             // water

            effectMaterial.Parameters.Add(VertexTextureTerrainKeys.MeshTexture0, tex1);
            effectMaterial.Parameters.Add(VertexTextureTerrainKeys.MeshTexture1, tex0);
            effectMaterial.Parameters.Add(VertexTextureTerrainKeys.MeshTexture2, tex2);

            effectMaterial.Parameters.Add(MaterialKeys.DiffuseMap, tex1);

            //terrainMesh = new Mesh { Draw = meshDraw /*, Material = LoadAsset<Material>("TerrainMaterial")*/ };
            terrainMesh = new Mesh {
                Draw = meshDraw, MaterialIndex = 0
            };

            //terrainEntity = new Entity { { ModelComponent.Key, new ModelComponent { Model = new Model { terrainMesh } } } };
            //TerrainEntity.Add<ModelComponent>( ModelComponent.Key, new ModelComponent { Model = new Model { terrainMesh } } );
            TerrainEntity.Add <ModelComponent>(ModelComponent.Key, new ModelComponent {
                Model = new Model {
                    terrainMesh, effectMaterial
                }
            });
        }
示例#20
0
        void MakeNumberMesh(float location, int number, float size)
        {
            if (number > -1 && number < 10)
            {
                for (int line = 0; line < 7; line++)
                {
                    if (Numbers[number].Lines[line])
                    {
                        float Xstart = m_NumberLineStart[line].X * (size * 1.25f) + location;
                        float Ystart = m_NumberLineStart[line].Y * size;

                        float Xend = m_NumberLineEnd[line].X * (size * 1.25f) + location;
                        float Yend = m_NumberLineEnd[line].Y * size;

                        Vector3 start = new Vector3(Xstart, Ystart, 0); //numbers->getMesh()->addVertex(Xstart, Ystart, 0);
                        Vector3 end   = new Vector3(Xend, Yend, 0);     //numbers->getMesh()->addVertex(Xend, Yend, 0);


                        // VertexPositionNormalTexture is the layout that the engine uses in the shaders
                        var vBuffer = Xenko.Graphics.Buffer.Vertex.New(GraphicsDevice, new VertexPositionNormalTexture[]
                        {
                            new VertexPositionNormalTexture(start, new Vector3(0, 1, 1), new Vector2(0, 0)), //Top.
                            new VertexPositionNormalTexture(end, new Vector3(0, 1, 1), new Vector2(0, 0)),   //Bottom right.
                        });

                        MeshDraw meshDraw = new MeshDraw
                        {
                            PrimitiveType = PrimitiveType.LineStrip, // Tell the GPU that this is a line.
                            VertexBuffers = new[] { new VertexBufferBinding(vBuffer, VertexPositionNormalTexture.Layout, vBuffer.ElementCount) },
                            DrawCount     = vBuffer.ElementCount
                        };

                        Mesh mesh = new Mesh();
                        mesh.Draw = meshDraw;

                        Model model = new Model();
                        model.Add(mesh);
                        m_NumberMeshs.Add(new ModelComponent(model));
                        m_Numbers.Add(new Entity());
                        m_Numbers[m_Numbers.Count - 1].Add(m_NumberMeshs[m_NumberMeshs.Count - 1]);
                        this.Entity.AddChild(m_Numbers[m_Numbers.Count - 1]);
                    }
                }
            }
        }
示例#21
0
            public void Build()
            {
                var indices  = new int[12 * 2];
                var vertices = new VertexPositionNormalTexture[8];

                vertices[0] = new VertexPositionNormalTexture(new Vector3(-1, 1, -1), Vector3.UnitY, Vector2.Zero);
                vertices[1] = new VertexPositionNormalTexture(new Vector3(-1, 1, 1), Vector3.UnitY, Vector2.Zero);
                vertices[2] = new VertexPositionNormalTexture(new Vector3(1, 1, 1), Vector3.UnitY, Vector2.Zero);
                vertices[3] = new VertexPositionNormalTexture(new Vector3(1, 1, -1), Vector3.UnitY, Vector2.Zero);

                int indexOffset = 0;

                // Top sides
                for (int i = 0; i < 4; i++)
                {
                    indices[indexOffset++] = i;
                    indices[indexOffset++] = (i + 1) % 4;
                }

                // Duplicate vertices and indices to bottom part
                for (int i = 0; i < 4; i++)
                {
                    vertices[i + 4]            = vertices[i];
                    vertices[i + 4].Position.Y = -vertices[i + 4].Position.Y;

                    indices[indexOffset++] = indices[i * 2] + 4;
                    indices[indexOffset++] = indices[i * 2 + 1] + 4;
                }

                // Sides
                for (int i = 0; i < 4; i++)
                {
                    indices[indexOffset++] = i;
                    indices[indexOffset++] = i + 4;
                }

                vertexBuffer = Buffer.Vertex.New(graphicsDevice, vertices);
                MeshDraw     = new MeshDraw
                {
                    PrimitiveType = PrimitiveType.LineList,
                    DrawCount     = indices.Length,
                    IndexBuffer   = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices), true, indices.Length),
                    VertexBuffers = new[] { new VertexBufferBinding(vertexBuffer, VertexPositionNormalTexture.Layout, vertexBuffer.ElementCount) },
                };
            }
示例#22
0
        /// <summary>
        /// Compacts the index buffer from 32 bits to 16 bits per index, if possible.
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        /// <returns>Returns true if index buffer was actually compacted.</returns>
        /// <exception cref="System.NotImplementedException"></exception>
        public static unsafe bool CompactIndexBuffer(this MeshDraw meshData)
        {
            // Already processed?
            if (meshData.IndexBuffer == null || !meshData.IndexBuffer.Is32Bit)
            {
                return(false);
            }

            // For now, require a MeshData with only one vertex buffer and no index buffer
            if (meshData.VertexBuffers.Length != 1)
            {
                throw new NotImplementedException();
            }

            var vertexBufferBinding = meshData.VertexBuffers[0];
            var vertexCount         = vertexBufferBinding.Count;

            // Can't compact?
            // Note that 65536 could be valid, but 0xFFFF is kept for primitive restart in strips.
            if (vertexCount >= 65536 || !meshData.IndexBuffer.Is32Bit)
            {
                return(false);
            }

            // Create new index buffer
            var indexCount      = meshData.IndexBuffer.Count;
            var indexBufferData = new byte[indexCount * Utilities.SizeOf <ushort>()];

            fixed(byte *oldIndexBufferDataStart = &meshData.IndexBuffer.Buffer.GetDataSafe()[0])
            fixed(byte *indexBufferDataStart = &indexBufferData[0])
            {
                var oldIndexBufferDataPtr = (int *)oldIndexBufferDataStart;
                var indexBufferDataPtr    = (ushort *)indexBufferDataStart;

                for (int i = 0; i < indexCount; ++i)
                {
                    // This also works to convert 0xFFFFFFFF into 0xFFFF (primitive restart in strips).
                    *indexBufferDataPtr++ = (ushort)*oldIndexBufferDataPtr++;
                }

                meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), false, indexCount);
            }

            return(true);
        }
示例#23
0
        /// <summary>
        /// Creates an Entity that contains our dynamic Vertex and Index buffers.
        /// This Entity will be rendered by the model renderer.
        /// </summary>
        /// <param name="verticesCount"></param>
        /// <param name="indicesCount"></param>
        private void CreateTerrainModelEntity(int verticesCount, int indicesCount)
        {
            // Compute sizes
            var vertexDeclaration = VertexNormalTexture.VertexDeclaration;
            var vertexBufferSize  = verticesCount * vertexDeclaration.CalculateSize();
            var indexBufferSize   = indicesCount * sizeof(short);

            // Create Vertex and Index buffers
            terrainVertexBuffer = Buffer.Vertex.New(GraphicsDevice, vertexBufferSize, GraphicsResourceUsage.Dynamic);
            terrainIndexBuffer  = Buffer.New(GraphicsDevice, indexBufferSize, BufferFlags.IndexBuffer, GraphicsResourceUsage.Dynamic);

            // Prepare mesh and entity
            var meshDraw = new MeshDraw
            {
                PrimitiveType = PrimitiveType.TriangleStrip,
                VertexBuffers = new[] { new VertexBufferBinding(terrainVertexBuffer, vertexDeclaration, verticesCount) },
                IndexBuffer   = new IndexBufferBinding(terrainIndexBuffer, false, indicesCount),
            };

            // Load the material and set parameters
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture0, WaterTexture);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture1, GrassTexture);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MeshTexture2, MountainTexture);

            // Set up material regions
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight0, -10);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight0, 40);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight0, 70);

            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight1, 60);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight1, 80);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight1, 90);

            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MinimumHeight2, 85);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.OptimalHeight2, 95);
            TerrainMaterial.Parameters.Set(VertexTextureTerrainKeys.MaximumHeight2, 125);

            terrainMesh = new Mesh {
                Draw = meshDraw, MaterialIndex = 0
            };
            TerrainEntity.GetOrCreate <ModelComponent>().Model = new Model {
                terrainMesh, TerrainMaterial
            };
        }
示例#24
0
            protected Entity AddModelEntity(string suffix, MeshDraw mesh, Material material, Quaternion rotation = default, Vector3 position = default)
            {
                var entity = new Entity($"Model_{suffix}");

                entity.Transform.Position = position;
                entity.Transform.Rotation = rotation;
                entity.Add(new ModelComponent
                {
                    Model = new Model {
                        material, new Mesh {
                            Draw = mesh
                        }
                    },
                    RenderGroup = GizmoRenderGroup,
                });

                ModelEntity.AddChild(entity);
                return(entity);
            }
示例#25
0
        /// <summary>
        /// Extracts a selection of vertices from a vertex buffer stored in this mesh data.
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        /// <param name="vertexElementToExtract">The declaration to extract (e.g. "POSITION0"...etc.) </param>
        public static T[] GetVertexBufferData <T>(this MeshDraw meshData, params string[] vertexElementToExtract) where T : struct
        {
            var declaration = meshData.VertexBuffers[0].Declaration;

            var offsets = declaration.EnumerateWithOffsets().Where(vertexElementOffset => vertexElementToExtract.Contains(vertexElementOffset.VertexElement.SemanticAsText)).ToList();

            int expectedSize = offsets.Sum(vertexElementWithOffset => vertexElementWithOffset.Size);

            var count = meshData.VertexBuffers[0].Count;

            int outputSize = expectedSize * count;

            int checkSize = (int)(outputSize / Utilities.SizeOf <T>()) * Utilities.SizeOf <T>();

            if (checkSize != outputSize)
            {
                throw new ArgumentException(string.Format("Size of T is not a multiple of totalSize {0}", outputSize));
            }

            var output = new T[outputSize / Utilities.SizeOf <T>()];

            var handleOutput = GCHandle.Alloc(output, GCHandleType.Pinned);
            var ptrOutput    = handleOutput.AddrOfPinnedObject();

            var handleInput = GCHandle.Alloc(meshData.VertexBuffers[0].Buffer.GetSerializationData().Content, GCHandleType.Pinned);
            var ptrInput    = handleInput.AddrOfPinnedObject();

            for (int i = 0; i < count; i++)
            {
                foreach (var vertexElementWithOffset in offsets)
                {
                    Utilities.CopyMemory(ptrOutput, ptrInput + vertexElementWithOffset.Offset, vertexElementWithOffset.Size);
                    ptrOutput = ptrOutput + vertexElementWithOffset.Size;
                }
                ptrInput += declaration.VertexStride;
            }

            handleInput.Free();
            handleOutput.Free();
            return(output);
        }
示例#26
0
        private void Draw(RenderDrawContext context, MeshDraw drawData, Vector4 color, DepthStencilStateDescription depthStencilState)
        {
            pipelineState.State.DepthStencilState = depthStencilState;
            pipelineState.State.Output.CaptureState(context.CommandList);
            pipelineState.Update();

            context.CommandList.SetIndexBuffer(drawData.IndexBuffer.Buffer, drawData.IndexBuffer.Offset, drawData.IndexBuffer.Is32Bit);
            context.CommandList.SetPipelineState(pipelineState.CurrentState);

            shader.Parameters.Set(SelectionWireframeShaderKeys.LineColor, color);
            shader.Apply(context.GraphicsContext);

            if (drawData.IndexBuffer != null)
            {
                context.CommandList.DrawIndexed(drawData.DrawCount, drawData.StartLocation);
            }
            else
            {
                context.CommandList.Draw(drawData.DrawCount, drawData.StartLocation);
            }
        }
示例#27
0
        public override void Draw(RenderDrawContext context, RenderView renderView, RenderViewStage renderViewStage)
        {
            float blendValue = (selectionService?.DisplaySelectionMask ?? false)
                ? 1.0f
                : MathUtil.Clamp((1.0f - (float)clockSelection.Elapsed.TotalSeconds), 0.0f, 1.0f);

            shader.UpdateEffect(context.GraphicsDevice);

            foreach (var renderNode in renderViewStage.SortedRenderNodes)
            {
                var renderMesh = renderNode.RenderObject as RenderMesh;
                if (renderMesh == null)
                {
                    continue;
                }

                MeshDraw drawData = renderMesh.ActiveMeshDraw;

                // bind VB
                for (int slot = 0; slot < drawData.VertexBuffers.Length; slot++)
                {
                    var vertexBuffer = drawData.VertexBuffers[slot];
                    context.CommandList.SetVertexBuffer(slot, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                }

                // set shader parameters
                shader.Parameters.Set(SelectionWireframeShaderKeys.WorldViewProjection, renderMesh.World * renderView.ViewProjection); // matrix
                shader.Parameters.Set(SelectionWireframeShaderKeys.WorldScale, new Vector3(1.0001f));                                  // increase scale to avoid z-fight
                shader.Parameters.Set(SelectionWireframeShaderKeys.Viewport, new Vector4(context.RenderContext.RenderView.ViewSize, 0, 0));
                shader.Parameters.Set(SelectionWireframeShaderKeys.LineWidth, LineWidth);

                // prepare pipeline state
                pipelineState.State.RootSignature  = shader.RootSignature;
                pipelineState.State.EffectBytecode = shader.Effect.Bytecode;
                pipelineState.State.PrimitiveType  = drawData.PrimitiveType;

                Draw(context, drawData, GetColor(ColorOccludedLines, blendValue), DepthStencilStates.None);           // occluded
                Draw(context, drawData, GetColor(ColorNonOccludedLines, blendValue), DepthStencilStates.DepthRead);   // non-occluded
            }
        }
示例#28
0
        /// <summary>
        /// Generates an index buffer for this mesh data.
        /// </summary>
        /// <param name="meshData">The mesh data.</param>
        /// <param name="declaration">The final vertex declaration</param>
        public static unsafe void GenerateIndexBuffer(this MeshDraw meshData, VertexDeclaration declaration)
        {
            // For now, require a MeshData with only one vertex buffer and no index buffer
            if (meshData.VertexBuffers.Length != 1 || meshData.IndexBuffer != null)
            {
                throw new NotImplementedException();
            }

            var oldVertexBuffer = meshData.VertexBuffers[0];
            var oldVertexStride = oldVertexBuffer.Declaration.VertexStride;
            var newVertexStride = declaration.VertexStride;
            var indexMapping    = GenerateIndexMapping(oldVertexBuffer, null);
            var vertices        = indexMapping.Vertices;

            // Generate vertex buffer
            var vertexBufferData = new byte[declaration.VertexStride * indexMapping.Vertices.Length];

            fixed(byte *oldVertexBufferDataStart = &oldVertexBuffer.Buffer.GetDataSafe()[oldVertexBuffer.Offset])
            fixed(byte *vertexBufferDataStart = &vertexBufferData[0])
            {
                var vertexBufferDataCurrent = vertexBufferDataStart;

                for (int i = 0; i < vertices.Length; ++i)
                {
                    Utilities.CopyMemory((IntPtr)vertexBufferDataCurrent, new IntPtr(&oldVertexBufferDataStart[oldVertexStride * vertices[i]]), newVertexStride);
                    vertexBufferDataCurrent += newVertexStride;
                }
                meshData.VertexBuffers[0] = new VertexBufferBinding(new BufferData(BufferFlags.VertexBuffer, vertexBufferData).ToSerializableVersion(), declaration, indexMapping.Vertices.Length);
            }

            // Generate index buffer
            var indexBufferData = new byte[indexMapping.Indices.Length * Utilities.SizeOf <int>()];

            fixed(int *indexDataStart = &indexMapping.Indices[0])
            fixed(byte *indexBufferDataStart = &indexBufferData[0])
            {
                Utilities.CopyMemory((IntPtr)indexBufferDataStart, (IntPtr)indexDataStart, indexBufferData.Length);
                meshData.IndexBuffer = new IndexBufferBinding(new BufferData(BufferFlags.IndexBuffer, indexBufferData).ToSerializableVersion(), true, indexMapping.Indices.Length);
            }
        }
示例#29
0
        public override MeshDraw CreateDebugPrimitive(GraphicsDevice device)
        {
            if (cachedDebugPrimitive != null)
            {
                return(cachedDebugPrimitive);
            }

            var verts = new VertexPositionNormalTexture[pointsList.Count];

            for (var i = 0; i < pointsList.Count; i++)
            {
                verts[i].Position          = pointsList[i];
                verts[i].TextureCoordinate = Vector2.Zero;
                verts[i].Normal            = Vector3.Zero;
            }

            var intIndices = indicesList.Select(x => (int)x).ToArray();

            ////calculate basic normals
            ////todo verify, winding order might be wrong?
            for (var i = 0; i < indicesList.Count; i += 3)
            {
                var i1 = intIndices[i];
                var i2 = intIndices[i + 1];
                var i3 = intIndices[i + 2];
                var a  = verts[i1];
                var b  = verts[i2];
                var c  = verts[i3];
                var n  = Vector3.Cross((b.Position - a.Position), (c.Position - a.Position));
                n.Normalize();
                verts[i1].Normal = verts[i2].Normal = verts[i3].Normal = n;
            }

            var meshData = new GeometricMeshData <VertexPositionNormalTexture>(verts, intIndices, false);

            cachedDebugPrimitive = new GeometricPrimitive(device, meshData).ToMeshDraw();

            return(cachedDebugPrimitive);
        }
示例#30
0
        /// <summary>
        /// Determines whether the specified mesh draw data is simple.
        /// A <see cref="MeshDrawData"/> is simple if:
        /// * It contains only one <see cref="VertexBufferBindingData"/>, which must be simple.
        /// * It contains either no <see cref="IndexBufferBindingData"/>, or a simple one.
        /// * StartLocation is 0.
        /// * DrawCount is IndexBuffer.Count if there is an index buffer, otherwise VertexBuffers[0].Count.
        /// </summary>
        /// <param name="meshDrawData">The mesh draw data.</param>
        /// <returns></returns>
        public static bool IsSimple(this MeshDraw meshDrawData)
        {
            if (meshDrawData.VertexBuffers.Length != 1)
            {
                return(false);
            }

            if (!meshDrawData.VertexBuffers[0].IsSimple())
            {
                return(false);
            }

            if (meshDrawData.IndexBuffer != null)
            {
                if (!meshDrawData.IndexBuffer.IsSimple())
                {
                    return(false);
                }

                if (meshDrawData.DrawCount != meshDrawData.IndexBuffer.Count)
                {
                    return(false);
                }
            }
            else
            {
                if (meshDrawData.DrawCount != meshDrawData.VertexBuffers[0].Count)
                {
                    return(false);
                }
            }

            if (meshDrawData.StartLocation != 0)
            {
                return(false);
            }

            return(true);
        }
        public void Generate(IServiceRegistry services, Model model)
        {
            if (model == null) throw new ArgumentNullException(nameof(model));

            var needsTempDevice = false;
            var graphicsDevice = services?.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice;
            if (graphicsDevice == null)
            {
                graphicsDevice = GraphicsDevice.New();
                needsTempDevice = true;
            }

            var data = CreatePrimitiveMeshData();

            if (data.Vertices.Length == 0)
            {
                throw new InvalidOperationException("Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array");
            }

            if (LocalOffset != Vector3.Zero)
            {
                for (var index = 0; index < data.Vertices.Length; index++)
                {
                    data.Vertices[index].Position += LocalOffset;
                }
            }

            //Scale if necessary
            if (Scale != Vector3.One)
            {
                var inverseMatrix = Matrix.Scaling(Scale);
                inverseMatrix.Invert();
                for (var index = 0; index < data.Vertices.Length; index++)
                {
                    data.Vertices[index].Position *= Scale;
                    Vector3.TransformCoordinate(ref data.Vertices[index].Normal, ref inverseMatrix, out data.Vertices[index].Normal);
                }
            }

            var boundingBox = BoundingBox.Empty;
            for (int i = 0; i < data.Vertices.Length; i++)
                BoundingBox.Merge(ref boundingBox, ref data.Vertices[i].Position, out boundingBox);

            BoundingSphere boundingSphere;
            unsafe
            {
                fixed (void* verticesPtr = data.Vertices)
                    BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, data.Vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere);
            }

            var originalLayout = data.Vertices[0].GetLayout();

            // Generate Tangent/BiNormal vectors
            var resultWithTangentBiNormal = VertexHelper.GenerateTangentBinormal(originalLayout, data.Vertices, data.Indices);

            // Generate Multitexcoords
            var result = VertexHelper.GenerateMultiTextureCoordinates(resultWithTangentBiNormal);

            var meshDraw = new MeshDraw();

            var layout = result.Layout;
            var vertexBuffer = result.VertexBuffer;
            var indices = data.Indices;

            if (indices.Length < 0xFFFF)
            {
                var indicesShort = new ushort[indices.Length];
                for (int i = 0; i < indicesShort.Length; i++)
                {
                    indicesShort[i] = (ushort)indices[i];
                }
                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort), false, indices.Length);
                if (needsTempDevice)
                {
                    var indexData = BufferData.New(BufferFlags.IndexBuffer, indicesShort);
                    meshDraw.IndexBuffer = new IndexBufferBinding(indexData.ToSerializableVersion(), false, indices.Length);
                }
            }
            else
            {
                if (graphicsDevice.Features.CurrentProfile <= GraphicsProfile.Level_9_3)
                {
                    throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3");
                }

                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length);
                if (needsTempDevice)
                {
                    var indexData = BufferData.New(BufferFlags.IndexBuffer, indices);
                    meshDraw.IndexBuffer = new IndexBufferBinding(indexData.ToSerializableVersion(), true, indices.Length);
                }
            }

            meshDraw.VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertexBuffer, BufferFlags.VertexBuffer).RecreateWith(vertexBuffer), layout, data.Vertices.Length) };
            if (needsTempDevice)
            {
                var vertexData = BufferData.New(BufferFlags.VertexBuffer, vertexBuffer);
                meshDraw.VertexBuffers = new[] { new VertexBufferBinding(vertexData.ToSerializableVersion(), layout, data.Vertices.Length) };
            }

            meshDraw.DrawCount = indices.Length;
            meshDraw.PrimitiveType = PrimitiveType.TriangleList;

            var mesh = new Mesh { Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere };

            model.BoundingBox = boundingBox;
            model.BoundingSphere = boundingSphere;
            model.Add(mesh);

            if (MaterialInstance?.Material != null)
            {
                model.Materials.Add(MaterialInstance);
            }

            if (needsTempDevice)
            {
                graphicsDevice.Dispose();
            }
        }
示例#32
0
        /// <param name="context"></param>
        /// <inheritdoc/>
        public override void PrepareEffectPermutations(RenderDrawContext context)
        {
            var renderEffects = RootRenderFeature.RenderData.GetData(renderEffectKey);
            var tessellationStates = RootRenderFeature.RenderData.GetData(tessellationStateKey);
            int effectSlotCount = ((RootEffectRenderFeature)RootRenderFeature).EffectPermutationSlotCount;

            foreach (var renderObject in RootRenderFeature.RenderObjects)
            {
                var staticObjectNode = renderObject.StaticObjectNode;

                var renderMesh = (RenderMesh)renderObject;

                var material = renderMesh.Material;
                var materialInfo = renderMesh.MaterialInfo;

                // Material use first 16 bits
                var materialHashCode = material != null ? (uint)material.GetHashCode() : 0;
                renderObject.StateSortKey = (renderObject.StateSortKey & 0x0000FFFF) | (materialHashCode << 16);

                var tessellationState = tessellationStates[staticObjectNode];

                // Update draw data if tessellation is active
                if (material.TessellationMethod != XenkoTessellationMethod.None)
                {
                    var tessellationMeshDraw = tessellationState.MeshDraw;

                    if (tessellationState.Method != material.TessellationMethod)
                    {
                        tessellationState.Method = material.TessellationMethod;

                        var oldMeshDraw = renderMesh.ActiveMeshDraw;
                        tessellationMeshDraw = new MeshDraw
                        {
                            VertexBuffers = oldMeshDraw.VertexBuffers,
                            IndexBuffer = oldMeshDraw.IndexBuffer,
                            DrawCount = oldMeshDraw.DrawCount,
                            StartLocation = oldMeshDraw.StartLocation,
                            PrimitiveType = tessellationState.Method.GetPrimitiveType(),
                        };

                        // adapt the primitive type and index buffer to the tessellation used
                        if (tessellationState.Method.PerformsAdjacentEdgeAverage())
                        {
                            renderMeshesToGenerateAEN.Add(renderMesh);
                        }
                        else
                        {
                            // Not using AEN tessellation anymore, dispose AEN indices if they were generated
                            Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN);
                        }
                        tessellationState.MeshDraw = tessellationMeshDraw;

                        // Save back new state
                        tessellationStates[staticObjectNode] = tessellationState;

                        // Reset pipeline states
                        for (int i = 0; i < effectSlotCount; ++i)
                        {
                            var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                            var renderEffect = renderEffects[staticEffectObjectNode];

                            if (renderEffect != null)
                                renderEffect.PipelineState = null;
                        }
                    }

                    renderMesh.ActiveMeshDraw = tessellationState.MeshDraw;
                }
                else if (tessellationState.GeneratedIndicesAEN != null)
                {
                    // Not using tessellation anymore, dispose AEN indices if they were generated
                    Utilities.Dispose(ref tessellationState.GeneratedIndicesAEN);
                }

                for (int i = 0; i < effectSlotCount; ++i)
                {
                    var staticEffectObjectNode = staticObjectNode * effectSlotCount + i;
                    var renderEffect = renderEffects[staticEffectObjectNode];

                    // Skip effects not used during this frame
                    if (renderEffect == null || !renderEffect.IsUsedDuringThisFrame(RenderSystem))
                        continue;

                    if (materialInfo == null || materialInfo.Material != material)
                    {
                        // First time this material is initialized, let's create associated info
                        if (!allMaterialInfos.TryGetValue(material, out materialInfo))
                        {
                            materialInfo = new MaterialInfo(material);
                            allMaterialInfos.Add(material, materialInfo);
                        }
                        renderMesh.MaterialInfo = materialInfo;
                    }

                    if (materialInfo.CullMode != material.CullMode)
                    {
                        materialInfo.CullMode = material.CullMode;
                        renderEffect.PipelineState = null;
                    }

                    var isMaterialParametersChanged = materialInfo.MaterialParameters != material.Parameters;
                    if (isMaterialParametersChanged // parameter fast reload?
                        || materialInfo.PermutationCounter != material.Parameters.PermutationCounter)
                    {
                        materialInfo.VertexStageSurfaceShaders = material.Parameters.Get(MaterialKeys.VertexStageSurfaceShaders);
                        materialInfo.VertexStageStreamInitializer = material.Parameters.Get(MaterialKeys.VertexStageStreamInitializer);

                        materialInfo.DomainStageSurfaceShaders = material.Parameters.Get(MaterialKeys.DomainStageSurfaceShaders);
                        materialInfo.DomainStageStreamInitializer = material.Parameters.Get(MaterialKeys.DomainStageStreamInitializer);

                        materialInfo.TessellationShader = material.Parameters.Get(MaterialKeys.TessellationShader);

                        materialInfo.PixelStageSurfaceShaders = material.Parameters.Get(MaterialKeys.PixelStageSurfaceShaders);
                        materialInfo.PixelStageStreamInitializer = material.Parameters.Get(MaterialKeys.PixelStageStreamInitializer);
                        materialInfo.HasNormalMap = material.Parameters.Get(MaterialKeys.HasNormalMap);

                        materialInfo.MaterialParameters = material.Parameters;
                        materialInfo.ParametersChanged = isMaterialParametersChanged;
                        materialInfo.PermutationCounter = material.Parameters.PermutationCounter;
                    }

                    // VS
                    if (materialInfo.VertexStageSurfaceShaders != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageSurfaceShaders, materialInfo.VertexStageSurfaceShaders);
                    if (materialInfo.VertexStageStreamInitializer != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.VertexStageStreamInitializer, materialInfo.VertexStageStreamInitializer);

                    // DS
                    if (materialInfo.DomainStageSurfaceShaders != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageSurfaceShaders, materialInfo.DomainStageSurfaceShaders);
                    if (materialInfo.DomainStageStreamInitializer != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.DomainStageStreamInitializer, materialInfo.DomainStageStreamInitializer);

                    // Tessellation
                    if (materialInfo.TessellationShader != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.TessellationShader, materialInfo.TessellationShader);

                    // PS
                    if (materialInfo.PixelStageSurfaceShaders != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageSurfaceShaders, materialInfo.PixelStageSurfaceShaders);
                    if (materialInfo.PixelStageStreamInitializer != null)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.PixelStageStreamInitializer, materialInfo.PixelStageStreamInitializer);
                    if (materialInfo.HasNormalMap)
                        renderEffect.EffectValidator.ValidateParameter(MaterialKeys.HasNormalMap, materialInfo.HasNormalMap);
                }
            }
        }
        public void Generate(IServiceRegistry services, Model model)
        {
            if (services == null) throw new ArgumentNullException("services");
            if (model == null) throw new ArgumentNullException("model");

            var graphicsDevice = services.GetSafeServiceAs<IGraphicsDeviceService>().GraphicsDevice;

            var data = this.CreatePrimitiveMeshData();

            if (data.Vertices.Length == 0)
            {
                throw new InvalidOperationException("Invalid GeometricPrimitive [{0}]. Expecting non-zero Vertices array");
            }

            var boundingBox = BoundingBox.Empty;
            for (int i = 0; i < data.Vertices.Length; i++)
                BoundingBox.Merge(ref boundingBox, ref data.Vertices[i].Position, out boundingBox);

            BoundingSphere boundingSphere;
            unsafe
            {
                fixed (void* verticesPtr = data.Vertices)
                    BoundingSphere.FromPoints((IntPtr)verticesPtr, 0, data.Vertices.Length, VertexPositionNormalTexture.Size, out boundingSphere);
            }

            var originalLayout = data.Vertices[0].GetLayout();

            // Generate Tangent/BiNormal vectors
            var resultWithTangentBiNormal = VertexHelper.GenerateTangentBinormal(originalLayout, data.Vertices, data.Indices);

            // Generate Multitexcoords
            var result = VertexHelper.GenerateMultiTextureCoordinates(resultWithTangentBiNormal);

            var meshDraw = new MeshDraw();

            var layout = result.Layout;
            var vertexBuffer = result.VertexBuffer;
            var indices = data.Indices;

            if (indices.Length < 0xFFFF)
            {
                var indicesShort = new ushort[indices.Length];
                for (int i = 0; i < indicesShort.Length; i++)
                {
                    indicesShort[i] = (ushort)indices[i];
                }
                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indicesShort).RecreateWith(indicesShort), false, indices.Length);
            }
            else
            {
                if (graphicsDevice.Features.Profile <= GraphicsProfile.Level_9_3)
                {
                    throw new InvalidOperationException("Cannot generate more than 65535 indices on feature level HW <= 9.3");
                }

                meshDraw.IndexBuffer = new IndexBufferBinding(Buffer.Index.New(graphicsDevice, indices).RecreateWith(indices), true, indices.Length);
            }

            meshDraw.VertexBuffers = new[] { new VertexBufferBinding(Buffer.New(graphicsDevice, vertexBuffer, BufferFlags.VertexBuffer).RecreateWith(vertexBuffer), layout, data.Vertices.Length) };

            meshDraw.DrawCount = indices.Length;
            meshDraw.PrimitiveType = PrimitiveType.TriangleList;

            var mesh = new Mesh { Draw = meshDraw, BoundingBox = boundingBox, BoundingSphere = boundingSphere };

            model.BoundingBox = boundingBox;
            model.BoundingSphere = boundingSphere;
            model.Add(mesh);

            if (MaterialInstance != null && MaterialInstance.Material != null)
            {
                model.Materials.Add(MaterialInstance);
            }
        }