コード例 #1
0
        /// <summary>
        /// Function to create a vertex buffer and its binding.
        /// </summary>
        /// <typeparam name="T">The type of data representing a vertex, must be an unmanaged value type.</typeparam>
        /// <param name="graphics">The graphics interface that will create the buffer.</param>
        /// <param name="vertexCount">The total number vertices that the buffer can hold.</param>
        /// <param name="usage">[Optional] The intended usage for the buffer.</param>
        /// <param name="binding">[Optional] The binding options for the buffer.</param>
        /// <param name="initialData">[Optional] An initial set of vertex data to send to the buffer.</param>
        /// <param name="bindingIndex">[Optional] The index, in vertices, inside the buffer where binding is to begin.</param>
        /// <param name="bufferName">[Optional] A name for the buffer.</param>
        /// <returns>A new <see cref="GorgonVertexBufferBinding"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/> parameter is <b>null</b>.</exception>
        /// <remarks>
        /// <para>
        /// Use this to quickly create a vertex buffer and its binding based on a known vertex data type.
        /// </para>
        /// <para>
        /// Be aware that the <see cref="VertexBuffer"/> created by this method must be disposed manually after it is no longer of any use.
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonVertexBuffer"/>
        public static GorgonVertexBufferBinding CreateVertexBuffer <T>(GorgonGraphics graphics,
                                                                       int vertexCount,
                                                                       ResourceUsage usage = ResourceUsage.Default,
                                                                       VertexIndexBufferBinding binding   = VertexIndexBufferBinding.None,
                                                                       GorgonNativeBuffer <T> initialData = null,
                                                                       int bindingIndex  = 0,
                                                                       string bufferName = null)
            where T : unmanaged
        {
            if (graphics == null)
            {
                throw new ArgumentNullException(nameof(graphics));
            }

            int vertexSize = Unsafe.SizeOf <T>();
            var buffer     = new GorgonVertexBuffer(graphics,
                                                    new GorgonVertexBufferInfo(bufferName)
            {
                SizeInBytes = vertexCount * vertexSize,
                Binding     = binding,
                Usage       = usage
            },
                                                    initialData?.Cast <byte>());


            return(new GorgonVertexBufferBinding(buffer, vertexSize, bindingIndex * vertexSize));
        }
コード例 #2
0
        /// <summary>
        /// Function to build the plane vertices.
        /// </summary>
        /// <param name="buffer">Buffer to populate.</param>
        /// <param name="size">The width and height of the plane.</param>
        /// <param name="textureCoordinates">The texture coordinates to apply to the plane.</param>
        /// <param name="columns">The number of columns to subdivide by.</param>
        /// <param name="rows">The number of rows to subdivide by.</param>
        private void GetVertices(GorgonNativeBuffer <Vertex3D> buffer, DX.Vector2 size, RectangleF textureCoordinates, int columns, int rows)
        {
            float columnWidth  = 1.0f / columns;
            float columnHeight = 1.0f / rows;
            int   offset       = 0;

            DX.Vector3 vertexNormal = -DX.Vector3.UnitZ;
            DX.Vector3.TransformNormal(ref vertexNormal, ref _orientation, out vertexNormal);

            for (int y = 0; y <= rows; ++y)
            {
                for (int x = 0; x <= columns; ++x)
                {
                    var vertexPos = new DX.Vector3(((x * columnWidth) - 0.5f) * size.X,
                                                   ((y * columnHeight) - 0.5f) * size.Y,
                                                   0);

                    DX.Vector3.TransformCoordinate(ref vertexPos, ref _orientation, out vertexPos);

                    buffer[offset++] = new Vertex3D
                    {
                        Position =
                            new DX.Vector4(vertexPos,
                                           1.0f),
                        Normal = vertexNormal,
                        UV     = new DX.Vector2((x * (textureCoordinates.Width / columns)) + textureCoordinates.X,
                                                (1.0f - (y * (textureCoordinates.Height / rows))) + textureCoordinates.Y)
                    };
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Cube"/> class.
        /// </summary>
        /// <param name="graphics">The graphics object used to create the buffers needed by this object.</param>
        /// <param name="inputLayout">The input layout describing how a vertex is laid out.</param>
        public Cube(GorgonGraphics graphics, GorgonInputLayout inputLayout)
        {
            CubeVertex[] vertices =
            {
                new CubeVertex(new DX.Vector3(-0.5f,  0.5f, -0.5f), new DX.Vector3(0,       0, 0)),
                new CubeVertex(new DX.Vector3(0.5f,   0.5f, -0.5f), new DX.Vector3(1.0f, 1.0f, 0)),
                new CubeVertex(new DX.Vector3(0.5f,  -0.5f, -0.5f), new DX.Vector3(0.0f, 1.0f, 0)),
                new CubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector3(1.0f, 0.0f, 0)),

                new CubeVertex(new DX.Vector3(-0.5f,  0.5f,  0.5f), new DX.Vector3(0,       0, 0)),
                new CubeVertex(new DX.Vector3(0.5f,   0.5f,  0.5f), new DX.Vector3(1.0f, 1.0f, 0)),
                new CubeVertex(new DX.Vector3(0.5f,  -0.5f,  0.5f), new DX.Vector3(0.0f, 1.0f, 0)),
                new CubeVertex(new DX.Vector3(-0.5f, -0.5f,  0.5f), new DX.Vector3(1.0f, 0.0f, 0)),
            };

            ushort[] indices =
            {
                // Front face.
                0, 1, 2,
                2, 3, 0,
                // Back face.
                5, 4, 6,
                4, 7, 6,
                // Left face.
                4, 0, 3,
                3, 7, 4,
                // Right face.
                1, 5, 6,
                6, 2, 1,
                // Top face
                4, 5, 1,
                1, 0, 4,
                // Bottom face
                2, 6, 7,
                7, 3, 2
            };

            // Create our index buffer and vertex buffer and populate with our cube data.
            using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(indices))
                using (var vertexPtr = GorgonNativeBuffer <CubeVertex> .Pin(vertices))
                {
                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("Volume Index Buffer")
                    {
                        Usage           = ResourceUsage.Immutable,
                        IndexCount      = indices.Length,
                        Use16BitIndices = true
                    },
                                                        indexPtr);

                    VertexBuffer = new GorgonVertexBufferBindings(inputLayout)
                    {
                        [0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics,
                                                                           vertices.Length,
                                                                           ResourceUsage.Immutable,
                                                                           initialData: vertexPtr,
                                                                           bufferName: "Volume Vertex Buffer")
                    };
                }
        }
コード例 #4
0
ファイル: GorgonRawHID.cs プロジェクト: ishkang/Gorgon
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        public void Dispose()
        {
            _preParsedData?.Dispose();
            _preParsedData = null;

            GC.SuppressFinalize(this);
        }
コード例 #5
0
        /// <summary>
        /// Initializes a new instance of the <see cref="GorgonBuffer" /> class.
        /// </summary>
        /// <param name="graphics">The <see cref="GorgonGraphics"/> object used to create and manipulate the buffer.</param>
        /// <param name="info">Information used to create the buffer.</param>
        /// <param name="initialData">[Optional] The initial data used to populate the buffer.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="info"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentException">Thrown if the size of the buffer is less than 1 byte.</exception>
        /// <exception cref="GorgonException">Thrown if the buffer is created with a usage of <see cref="ResourceUsage.Immutable"/>, but the <paramref name="initialData"/> parameter is <b>null</b>.
        /// <para>-or-</para>
        /// <para>A value on the <paramref name="info"/> parameter is incorrect.</para>
        /// </exception>
        public GorgonBuffer(GorgonGraphics graphics, IGorgonBufferInfo info, GorgonNativeBuffer <byte> initialData = null)
            : base(graphics)
        {
            _info = new GorgonBufferInfo(info ?? throw new ArgumentNullException(nameof(info)));

            Initialize(initialData);
        }
コード例 #6
0
ファイル: Cube.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Initializes a new instance of the <see cref="Cube" /> class.
        /// </summary>
        /// <param name="graphics">The graphics interface.</param>
        /// <param name="size">The width, height and depth of the cube.</param>
        /// <param name="textureCoordinates">The texture coordinates for the faces of the cube.</param>
        /// <param name="angle">The initial orientation of the cube, in degrees.</param>
        /// <param name="columnsPerFace">The number of columns per face.</param>
        /// <param name="rowsPerFace">The number of rows per face.</param>
        public Cube(GorgonGraphics graphics, DX.Vector3 size, RectangleF textureCoordinates, DX.Vector3 angle, int columnsPerFace = 1, int rowsPerFace = 1)
            : base(graphics)
        {
            PrimitiveType = PrimitiveType.TriangleList;
            int faceVertexCount = (columnsPerFace + 1) * (rowsPerFace + 1);
            int faceIndexCount  = (columnsPerFace * rowsPerFace) * 6;

            VertexCount   = faceVertexCount * 6;
            IndexCount    = faceIndexCount * 6;
            TriangleCount = IndexCount / 3;

            DX.Quaternion.RotationYawPitchRoll(angle.Y.ToRadians(), angle.X.ToRadians(), angle.Z.ToRadians(), out DX.Quaternion orientation);
            DX.Matrix.RotationQuaternion(ref orientation, out _orientation);

            using (var vertexData = new GorgonNativeBuffer <Vertex3D>(VertexCount))
                using (var indexData = new GorgonNativeBuffer <int>(IndexCount))
                {
                    // Front.
                    GetVertices(vertexData, 0, DX.Vector3.UnitY, -DX.Vector3.UnitZ, size, textureCoordinates, columnsPerFace, rowsPerFace);
                    // Bottom.
                    GetVertices(vertexData, faceVertexCount, -DX.Vector3.UnitZ, -DX.Vector3.UnitY, size, textureCoordinates, columnsPerFace, rowsPerFace);
                    // Back.
                    GetVertices(vertexData, faceVertexCount * 2, DX.Vector3.UnitY, DX.Vector3.UnitZ, size, textureCoordinates, columnsPerFace, rowsPerFace);
                    // Top.
                    GetVertices(vertexData, faceVertexCount * 3, DX.Vector3.UnitZ, DX.Vector3.UnitY, size, textureCoordinates, columnsPerFace, rowsPerFace);
                    // Left.
                    GetVertices(vertexData, faceVertexCount * 4, DX.Vector3.UnitY, -DX.Vector3.UnitX, size, textureCoordinates, columnsPerFace, rowsPerFace);
                    // Right
                    GetVertices(vertexData, faceVertexCount * 5, DX.Vector3.UnitY, DX.Vector3.UnitX, size, textureCoordinates, columnsPerFace, rowsPerFace);

                    GetIndices(indexData, 0, 0, columnsPerFace, rowsPerFace);
                    GetIndices(indexData, faceIndexCount, faceVertexCount, columnsPerFace, rowsPerFace);
                    GetIndices(indexData, faceIndexCount * 2, faceVertexCount * 2, columnsPerFace, rowsPerFace);
                    GetIndices(indexData, faceIndexCount * 3, faceVertexCount * 3, columnsPerFace, rowsPerFace);
                    GetIndices(indexData, faceIndexCount * 4, faceVertexCount * 4, columnsPerFace, rowsPerFace);
                    GetIndices(indexData, faceIndexCount * 5, faceVertexCount * 5, columnsPerFace, rowsPerFace);

                    CalculateTangents(vertexData, indexData);

                    VertexBuffer = new GorgonVertexBuffer(graphics,
                                                          new GorgonVertexBufferInfo("CubeVB")
                    {
                        Usage       = ResourceUsage.Immutable,
                        SizeInBytes = vertexData.SizeInBytes
                    },
                                                          vertexData.Cast <byte>());


                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("CubeIB")
                    {
                        Usage           = ResourceUsage.Immutable,
                        Use16BitIndices = false,
                        IndexCount      = IndexCount
                    },
                                                        indexData);
                }
        }
コード例 #7
0
        /// <summary>
        /// Function to return the object.
        /// </summary>
        /// <returns>The object created or updated by this builder.</returns>
        /// <exception cref="GorgonException">Thrown if the polygonal sprite has less than 3 vertices.</exception>
        /// <remarks>
        /// <para>
        /// This will return a <see cref="GorgonPolySprite"/> for use with the <see cref="Gorgon2D.DrawPolygonSprite"/> method. The object returned implements <see cref="IDisposable"/>, so it is the
        /// responsibility of the user to dispose of the object when they are done with it.
        /// </para>
        /// <para>
        /// <note type="warning">
        /// <para>
        /// A polygon sprite must have a minimum of 3 vertices.  If it does not, then this method will throw an exception.
        /// </para>
        /// </note>
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonPolySprite"/>
        /// <seealso cref="Gorgon2D"/>
        public GorgonPolySprite Build()
        {
            if (_workingSprite.RwVertices.Count < 3)
            {
                throw new GorgonException(GorgonResult.CannotCreate, Resources.GOR2D_ERR_POLY_SPRITE_NOT_ENOUGH_VERTS);
            }

            var newSprite = new GorgonPolySprite();

            CopySprite(newSprite, _workingSprite);

            newSprite.Renderable.ActualVertexCount = newSprite.RwVertices.Count;
            if ((newSprite.Renderable.Vertices == null) || (newSprite.Renderable.Vertices.Length < newSprite.RwVertices.Count))
            {
                newSprite.Renderable.Vertices = new Gorgon2DVertex[newSprite.RwVertices.Count];
            }

            for (int i = 0; i < newSprite.RwVertices.Count; ++i)
            {
                newSprite.Renderable.Vertices[i] = newSprite.RwVertices[i].Vertex;
            }

            // Enforce clockwise ordering.
            _triangulator.EnsureWindingOrder(newSprite.Renderable.Vertices, WindingOrder.CounterClockwise);

            // Split the polygon hull into triangles.
            (GorgonNativeBuffer <int> indices, DX.RectangleF bounds) = _triangulator.Triangulate(newSprite.Renderable.Vertices, WindingOrder.CounterClockwise);
            GorgonNativeBuffer <Gorgon2DVertex> vertexData = newSprite.Renderable.Vertices.ToNativeBuffer();

            try
            {
                newSprite.Renderable.IndexBuffer = new GorgonIndexBuffer(Graphics, new GorgonIndexBufferInfo
                {
                    Binding         = VertexIndexBufferBinding.None,
                    Use16BitIndices = false,
                    IndexCount      = indices.Length,
                    Usage           = ResourceUsage.Immutable
                }, indices);


                newSprite.Renderable.VertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer(Graphics, new GorgonVertexBufferInfo
                {
                    Usage       = ResourceUsage.Immutable,
                    Binding     = VertexIndexBufferBinding.None,
                    SizeInBytes = Gorgon2DVertex.SizeInBytes * newSprite.RwVertices.Count
                }, vertexData);
                newSprite.Renderable.ActualVertexCount = newSprite.RwVertices.Count;
                newSprite.Renderable.IndexCount        = indices.Length;
                newSprite.Bounds = new DX.RectangleF(newSprite.Position.X, newSprite.Position.Y, bounds.Width, bounds.Height);
            }
            finally
            {
                vertexData?.Dispose();
                indices?.Dispose();
            }

            return(newSprite);
        }
コード例 #8
0
        /// <summary>
        /// Function to initialize the buffer data.
        /// </summary>
        /// <param name="initialData">The initial data used to populate the buffer.</param>
        private void Initialize <T>(GorgonNativeBuffer <T> initialData)
            where T : unmanaged
        {
            D3D11.CpuAccessFlags cpuFlags = GetCpuFlags(false, D3D11.BindFlags.IndexBuffer);

            Log.Print($"{Name} Index Buffer: Creating D3D11 buffer. Size: {SizeInBytes} bytes", LoggingLevel.Simple);

            GorgonVertexBuffer.ValidateBufferBindings(_info.Usage, 0);

            D3D11.BindFlags bindFlags = D3D11.BindFlags.IndexBuffer;

            if ((_info.Binding & VertexIndexBufferBinding.StreamOut) == VertexIndexBufferBinding.StreamOut)
            {
                bindFlags |= D3D11.BindFlags.StreamOutput;
            }

            if ((_info.Binding & VertexIndexBufferBinding.UnorderedAccess) == VertexIndexBufferBinding.UnorderedAccess)
            {
                bindFlags |= D3D11.BindFlags.UnorderedAccess;
            }

            var desc = new D3D11.BufferDescription
            {
                SizeInBytes         = SizeInBytes,
                Usage               = (D3D11.ResourceUsage)_info.Usage,
                BindFlags           = bindFlags,
                OptionFlags         = D3D11.ResourceOptionFlags.None,
                CpuAccessFlags      = cpuFlags,
                StructureByteStride = 0
            };

            if ((initialData != null) && (initialData.Length > 0))
            {
                unsafe
                {
                    D3DResource = Native = new D3D11.Buffer(Graphics.D3DDevice, new IntPtr((void *)initialData), desc)
                    {
                        DebugName = Name
                    };
                }
            }
            else
            {
                D3DResource = Native = new D3D11.Buffer(Graphics.D3DDevice, desc)
                {
                    DebugName = Name
                };
            }
        }
コード例 #9
0
ファイル: Plane.cs プロジェクト: ishkang/Gorgon
        /// <summary>
        /// Initializes a new instance of the <see cref="Plane" /> class.
        /// </summary>
        /// <param name="graphics">The graphics interface used to create the buffers for this object.</param>
        /// <param name="inputLayout">The input layout for the vertices in this mesh.</param>
        /// <param name="size">The width and height of the plane.</param>
        /// <param name="textureCoordinates">Texture coordinates.</param>
        public Plane(GorgonGraphics graphics, GorgonInputLayout inputLayout, DX.Vector2 size, DX.RectangleF textureCoordinates)
            : base(inputLayout)
        {
            Size = size;

            // Create our vertices.
            Vertices = new[]
            {
                new BoingerVertex(new DX.Vector3(-size.X, size.Y, 0.0f), textureCoordinates.Location),
                new BoingerVertex(new DX.Vector3(size.X, size.Y, 0.0f), new DX.Vector2(textureCoordinates.Right, textureCoordinates.Top)),
                new BoingerVertex(new DX.Vector3(-size.X, -size.Y, 0.0f), new DX.Vector2(textureCoordinates.Left, textureCoordinates.Bottom)),
                new BoingerVertex(new DX.Vector3(size.X, -size.Y, 0.0f), new DX.Vector2(textureCoordinates.Right, textureCoordinates.Bottom))
            };

            // Create our indices.
            Indices = new ushort[]
            {
                0,
                1,
                2,
                2,
                1,
                3
            };

            // Copy the above vertex/index data into a vertex and index buffer so we can render our plane.
            using (var vertexPtr = GorgonNativeBuffer <BoingerVertex> .Pin(Vertices))
                using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(Indices))
                {
                    VertexBufferBindings[0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics,
                                                                                           new GorgonVertexBufferInfo("Plane Vertex Buffer")
                    {
                        SizeInBytes =
                            Vertices.Length * BoingerVertex.Size,
                        Usage = ResourceUsage.Immutable
                    },
                                                                                           vertexPtr);

                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("Plane Index Buffer")
                    {
                        Usage           = ResourceUsage.Immutable,
                        IndexCount      = Indices.Length,
                        Use16BitIndices = true
                    },
                                                        indexPtr);
                }
        }
コード例 #10
0
ファイル: Cube.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Function to build the plane indices.
        /// </summary>
        /// <param name="buffer">Buffer to populate.</param>
        /// <param name="offset">The offset into the buffer.</param>
        /// <param name="vertexStart">The starting vertex.</param>
        /// <param name="columns">Number of columns for the plane.</param>
        /// <param name="rows">Number of rows for the plane.</param>
        private static void GetIndices(GorgonNativeBuffer <int> buffer, int offset, int vertexStart, int columns, int rows)
        {
            int columnWrap = columns + 1;

            for (int row = 0; row < rows; ++row)
            {
                for (int column = 0; column < columns; ++column)
                {
                    buffer[offset++] = (column + (row * columnWrap)) + vertexStart;
                    buffer[offset++] = (column + ((row + 1) * columnWrap)) + vertexStart;
                    buffer[offset++] = ((column + 1) + (row * columnWrap)) + vertexStart;

                    buffer[offset++] = (column + ((row + 1) * columnWrap)) + vertexStart;
                    buffer[offset++] = ((column + 1) + ((row + 1) * columnWrap)) + vertexStart;
                    buffer[offset++] = ((column + 1) + (row * columnWrap)) + vertexStart;
                }
            }
        }
コード例 #11
0
ファイル: Cube.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Function to build the plane vertices.
        /// </summary>
        /// <param name="buffer">Buffer to populate.</param>
        /// <param name="vertexOffset">The offset into the buffer.</param>
        /// <param name="up">Up vector for orientation.</param>
        /// <param name="normal">The face normal.</param>
        /// <param name="size">The width and height of the plane.</param>
        /// <param name="textureCoordinates">The texture coordinates to apply to the plane.</param>
        /// <param name="columns">The number of columns to subdivide by.</param>
        /// <param name="rows">The number of rows to subdivide by.</param>
        private void GetVertices(GorgonNativeBuffer <Vertex3D> buffer, int vertexOffset, DX.Vector3 up, DX.Vector3 normal, DX.Vector3 size, RectangleF textureCoordinates, int columns, int rows)
        {
            float columnWidth  = 1.0f / columns;
            float columnHeight = 1.0f / rows;

            DX.Matrix rotation = DX.Matrix.Identity;

            DX.Vector3.Cross(ref normal, ref up, out DX.Vector3 orientVector);
            DX.Vector3.Multiply(ref normal, 0.5f, out DX.Vector3 translate);

            rotation.Row1 = (DX.Vector4)orientVector;
            rotation.Row2 = (DX.Vector4)up;
            rotation.Row3 = (DX.Vector4)normal;
            rotation.Row4 = new DX.Vector4(translate, 1);

            DX.Vector3.TransformCoordinate(ref normal, ref _orientation, out DX.Vector3 transformNormal);
            DX.Vector3.Normalize(ref transformNormal, out transformNormal);

            for (int y = 0; y <= rows; ++y)
            {
                for (int x = 0; x <= columns; ++x)
                {
                    var vertexPos = new DX.Vector3(((x * columnWidth) - 0.5f) * size.X,
                                                   ((y * columnHeight) - 0.5f) * size.Y,
                                                   0);

                    DX.Vector3.TransformCoordinate(ref vertexPos, ref rotation, out vertexPos);
                    DX.Vector3.TransformCoordinate(ref vertexPos, ref _orientation, out vertexPos);

                    buffer[vertexOffset++] = new Vertex3D
                    {
                        Position =
                            new DX.Vector4(vertexPos,
                                           1.0f),
                        Normal = transformNormal,
                        UV     = new DX.Vector2((x * (textureCoordinates.Width / columns)) + textureCoordinates.X,
                                                (1.0f - (y * (textureCoordinates.Height / rows))) + textureCoordinates.Y)
                    };
                }
            }
        }
コード例 #12
0
ファイル: Sphere.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Initializes a new instance of the <see cref="Sphere" /> class.
        /// </summary>
        /// <param name="graphics">Graphics interface to use.</param>
        /// <param name="radius">Radius of the sphere</param>
        /// <param name="textureCoordinates">The texture coordinates to apply to the sphere.</param>
        /// <param name="angle">The angle of rotation, in degrees.</param>
        /// <param name="ringCount">Number of rings in the sphere.</param>
        /// <param name="segmentCount">Number of segments in the sphere.</param>
        public Sphere(GorgonGraphics graphics, float radius, RectangleF textureCoordinates, DX.Vector3 angle, int ringCount = 8, int segmentCount = 16)
            : base(graphics)
        {
            // Calculate number of vertices and indices required for our sphere.
            PrimitiveType = PrimitiveType.TriangleList;
            VertexCount   = (ringCount + 1) * (segmentCount + 1);
            IndexCount    = 6 * ringCount * (segmentCount + 1);
            TriangleCount = IndexCount / 3;

            DX.Quaternion.RotationYawPitchRoll(angle.Y.ToRadians(), angle.X.ToRadians(), angle.Z.ToRadians(), out DX.Quaternion orientation);
            DX.Matrix.RotationQuaternion(ref orientation, out _orientation);

            using (var vertexData = new GorgonNativeBuffer <Vertex3D>(VertexCount))
                using (var indexData = new GorgonNativeBuffer <int>(IndexCount))
                {
                    GetVertices(vertexData,
                                indexData,
                                radius,
                                textureCoordinates,
                                ringCount,
                                segmentCount);

                    VertexBuffer = new GorgonVertexBuffer(graphics,
                                                          new GorgonVertexBufferInfo("SphereVertexBuffer")
                    {
                        Usage       = ResourceUsage.Immutable,
                        SizeInBytes = vertexData.SizeInBytes
                    },
                                                          vertexData.Cast <byte>());

                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("SphereIndexBuffer")
                    {
                        Usage           = ResourceUsage.Immutable,
                        Use16BitIndices = false,
                        IndexCount      = IndexCount
                    },
                                                        indexData);
                }
        }
コード例 #13
0
ファイル: Triangle.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Initializes a new instance of the <see cref="Triangle" /> class.
        /// </summary>
        /// <param name="graphics">The graphics interface.</param>
        /// <param name="point1">The 1st point in the triangle.</param>
        /// <param name="point2">The 2nd point in the triangle.</param>
        /// <param name="point3">The 3rd point in the triangle.</param>
        public Triangle(GorgonGraphics graphics, Vertex3D point1, Vertex3D point2, Vertex3D point3)
            : base(graphics)
        {
            PrimitiveType = PrimitiveType.TriangleList;
            VertexCount   = 3;
            IndexCount    = 3;
            TriangleCount = 1;

            point1.Tangent = new DX.Vector4(1.0f, 0, 0, 1.0f);
            point2.Tangent = new DX.Vector4(1.0f, 0, 0, 1.0f);
            point3.Tangent = new DX.Vector4(1.0f, 0, 0, 1.0f);

            using (var points = new GorgonNativeBuffer <Vertex3D>(3))
                using (var indices = new GorgonNativeBuffer <int>(3))
                {
                    points[0]  = point1;
                    points[1]  = point2;
                    points[2]  = point3;
                    indices[0] = 0;
                    indices[1] = 1;
                    indices[2] = 2;

                    VertexBuffer = new GorgonVertexBuffer(graphics,
                                                          new GorgonVertexBufferInfo("TriVB")
                    {
                        Usage       = ResourceUsage.Immutable,
                        SizeInBytes = Vertex3D.Size * 3
                    },
                                                          points.Cast <byte>());

                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("TriIB")
                    {
                        Usage           = ResourceUsage.Dynamic,
                        Use16BitIndices = false,
                        IndexCount      = 3
                    },
                                                        indices);
                }
        }
コード例 #14
0
        /// <summary>
        /// Function used to initalize the buffer.
        /// </summary>
        /// <param name="initialData">The data to copy into the buffer on creation.</param>
        private void Initialize(GorgonNativeBuffer <byte> initialData)
        {
            if (_info.SizeInBytes < 1)
            {
                throw new ArgumentException(string.Format(Resources.GORGFX_ERR_BUFFER_SIZE_TOO_SMALL, 1));
            }

            if ((_info.Usage == ResourceUsage.Immutable) && (initialData == null))
            {
                throw new GorgonException(GorgonResult.CannotCreate, Resources.GORGFX_ERR_BUFFER_IMMUTABLE_REQUIRES_DATA);
            }

            D3D11.BufferDescription desc = BuildBufferDesc(_info);

            // Implicitly allow reading for staging resources.
            if (_info.Usage == ResourceUsage.Staging)
            {
                _info.AllowCpuRead = true;
            }

            Log.Print($"{Name} Generic Buffer: Creating D3D11 buffer. Size: {SizeInBytes} bytes", LoggingLevel.Simple);

            if ((initialData != null) && (initialData.Length > 0))
            {
                unsafe
                {
                    D3DResource = Native = new D3D11.Buffer(Graphics.D3DDevice, new IntPtr((byte *)initialData), desc)
                    {
                        DebugName = $"{Name}_ID3D11Buffer"
                    };
                }
            }
            else
            {
                D3DResource = Native = new D3D11.Buffer(Graphics.D3DDevice, desc)
                {
                    DebugName = $"{Name}_ID3D11Buffer"
                };
            }
        }
コード例 #15
0
        /// <summary>
        /// Function to initialize the buffer data.
        /// </summary>
        /// <param name="initialData">The initial data used to populate the buffer.</param>
        private void Initialize(GorgonNativeBuffer <byte> initialData)
        {
            // If the buffer is not aligned to 16 bytes, then pad the size.
            _info.SizeInBytes = (_info.SizeInBytes + 15) & ~15;

            TotalConstantCount = _info.SizeInBytes / (sizeof(float) * 4);

            D3D11.CpuAccessFlags cpuFlags = GetCpuFlags(false, D3D11.BindFlags.ConstantBuffer);

            Log.Print($"{Name} Constant Buffer: Creating D3D11 buffer. Size: {_info.SizeInBytes} bytes", LoggingLevel.Simple);

            var desc = new D3D11.BufferDescription
            {
                SizeInBytes         = _info.SizeInBytes,
                Usage               = (D3D11.ResourceUsage)_info.Usage,
                BindFlags           = D3D11.BindFlags.ConstantBuffer,
                OptionFlags         = D3D11.ResourceOptionFlags.None,
                CpuAccessFlags      = cpuFlags,
                StructureByteStride = 0
            };

            if ((initialData != null) && (initialData.Length > 0))
            {
                unsafe
                {
                    D3DResource = Native = new D3D11.Buffer(Graphics.D3DDevice, new IntPtr((void *)initialData), desc)
                    {
                        DebugName = Name
                    };
                }
            }
            else
            {
                D3DResource = Native = new D3D11.Buffer(Graphics.D3DDevice, desc)
                {
                    DebugName = Name
                };
            }
        }
コード例 #16
0
ファイル: BatchRenderer.cs プロジェクト: ishkang/Gorgon
        /// <summary>
        /// Function to create the vertex/index buffers for the renderer.
        /// </summary>
        private void CreateBuffers()
        {
            // We don't need to update the index buffer ever.  So we can set up the indices right now.
            using (var indices = new GorgonNativeBuffer <ushort>(MaxSpriteCount * 6))
            {
                int    indexOffset = 0;
                ushort index       = 0;
                for (int i = 0; i < MaxSpriteCount; ++i)
                {
                    indices[indexOffset++] = index;
                    indices[indexOffset++] = (ushort)(index + 1);
                    indices[indexOffset++] = (ushort)(index + 2);
                    indices[indexOffset++] = (ushort)(index + 1);
                    indices[indexOffset++] = (ushort)(index + 3);
                    indices[indexOffset++] = (ushort)(index + 2);

                    index += 4;
                }

                VertexBuffer = GorgonVertexBufferBinding.CreateVertexBuffer <Gorgon2DVertex>(Graphics,
                                                                                             new GorgonVertexBufferInfo
                {
                    Usage       = ResourceUsage.Dynamic,
                    Binding     = VertexIndexBufferBinding.None,
                    SizeInBytes = Gorgon2DVertex.SizeInBytes * (MaxSpriteCount * 4)
                });

                IndexBuffer = new GorgonIndexBuffer(Graphics,
                                                    new GorgonIndexBufferInfo
                {
                    Usage      = ResourceUsage.Immutable,
                    Binding    = VertexIndexBufferBinding.None,
                    IndexCount = indices.Length
                },
                                                    indices);
            }
        }
コード例 #17
0
        /// <summary>
        /// Initializes a new instance of the <see cref="Plane" /> class.
        /// </summary>
        /// <param name="graphics">The graphics interface to use.</param>
        /// <param name="size">The width and height of the plane.</param>
        /// <param name="textureCoordinates">The texture coordinates to apply to the plane.</param>
        /// <param name="angle">The initial orientation, in degrees.</param>
        /// <param name="columns">The number of columns to subdivide by.</param>
        /// <param name="rows">The number of rows to subdivide by.</param>
        public Plane(GorgonGraphics graphics, DX.Vector2 size, RectangleF textureCoordinates, DX.Vector3 angle, int columns = 1, int rows = 1)
            : base(graphics)
        {
            PrimitiveType = PrimitiveType.TriangleStrip;
            VertexCount   = (columns + 1) * (rows + 1);
            IndexCount    = ((columns * rows) * 6) + (rows - 1);
            TriangleCount = (IndexCount - (rows - 1)) / 3;

            DX.Quaternion.RotationYawPitchRoll(angle.Y.ToRadians(), angle.X.ToRadians(), angle.Z.ToRadians(), out DX.Quaternion orientation);
            DX.Matrix.RotationQuaternion(ref orientation, out _orientation);

            using (var vertexData = new GorgonNativeBuffer <Vertex3D>(VertexCount))
                using (var indexData = new GorgonNativeBuffer <int>(IndexCount))
                {
                    GetVertices(vertexData, size, textureCoordinates, columns, rows);
                    GetIndices(indexData, columns, rows);

                    CalculateTangents(vertexData, indexData);

                    VertexBuffer = new GorgonVertexBuffer(graphics,
                                                          new GorgonVertexBufferInfo("PlaneVB")
                    {
                        Usage       = ResourceUsage.Immutable,
                        SizeInBytes = vertexData.SizeInBytes
                    },
                                                          vertexData.Cast <byte>());

                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo
                    {
                        Usage           = ResourceUsage.Immutable,
                        Use16BitIndices = false,
                        IndexCount      = IndexCount
                    },
                                                        indexData);
                }
        }
コード例 #18
0
        /// <summary>
        /// Function to build the plane indices.
        /// </summary>
        /// <param name="buffer">Buffer to populate.</param>
        /// <param name="columns">Number of columns for the plane.</param>
        /// <param name="rows">Number of rows for the plane.</param>
        private static void GetIndices(GorgonNativeBuffer <int> buffer, int columns, int rows)
        {
            int offset     = 0;
            int columnWrap = columns + 1;

            for (int row = 0; row < rows; ++row)
            {
                for (int column = 0; column < columns; ++column)
                {
                    buffer[offset++] = column + (row * columnWrap);
                    buffer[offset++] = column + ((row + 1) * columnWrap);
                    buffer[offset++] = (column + 1) + (row * columnWrap);

                    buffer[offset++] = column + ((row + 1) * columnWrap);
                    buffer[offset++] = (column + 1) + (row * columnWrap);
                    buffer[offset++] = (column + 1) + ((row + 1) * columnWrap);
                }

                if (row < rows - 1)
                {
                    buffer[offset++] = unchecked ((int)0xffffffff);
                }
            }
        }
コード例 #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GorgonIndexBuffer" /> class, initialized with <see cref="ushort"/> values for 16 bit index buffers.
 /// </summary>
 /// <param name="graphics">The <see cref="GorgonGraphics"/> object used to create and manipulate the buffer.</param>
 /// <param name="info">Information used to create the buffer.</param>
 /// <param name="initialData">The initial data used to populate the buffer.</param>
 /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, <paramref name="info"/> or the <paramref name="initialData"/> parameters are <b>null</b>.</exception>
 public GorgonIndexBuffer(GorgonGraphics graphics, IGorgonIndexBufferInfo info, GorgonNativeBuffer <ushort> initialData)
     : base(graphics)
 {
     _info = new GorgonIndexBufferInfo(info ?? throw new ArgumentNullException(nameof(info)));
     Initialize(initialData ?? throw new ArgumentNullException(nameof(initialData)));
 }
コード例 #20
0
ファイル: Cube.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Initializes a new instance of the <see cref="Cube"/> class.
        /// </summary>
        /// <param name="graphics">The graphics object used to create the buffers needed by this object.</param>
        /// <param name="inputLayout">The input layout describing how a vertex is laid out.</param>
        public Cube(GorgonGraphics graphics, GorgonInputLayout inputLayout)
        {
            GlassCubeVertex[] vertices =
            {
                // Front face.
                new GlassCubeVertex(new DX.Vector3(-0.5f,  0.5f, -0.5f), new DX.Vector2(0,       0)),
                new GlassCubeVertex(new DX.Vector3(0.5f,  -0.5f, -0.5f), new DX.Vector2(1.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector2(0.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(0.5f,   0.5f, -0.5f), new DX.Vector2(1.0f, 0.0f)),

                // Right face.
                new GlassCubeVertex(new DX.Vector3(0.5f,   0.5f, -0.5f), new DX.Vector2(0,       0)),
                new GlassCubeVertex(new DX.Vector3(0.5f,  -0.5f,  0.5f), new DX.Vector2(1.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(0.5f,  -0.5f, -0.5f), new DX.Vector2(0.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(0.5f,   0.5f,  0.5f), new DX.Vector2(1.0f, 0.0f)),

                // Back face.
                new GlassCubeVertex(new DX.Vector3(0.5f,   0.5f,  0.5f), new DX.Vector2(0,       0)),
                new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f,  0.5f), new DX.Vector2(1.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(0.5f,  -0.5f,  0.5f), new DX.Vector2(0.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(-0.5f,  0.5f,  0.5f), new DX.Vector2(1.0f, 0.0f)),

                // Left face.
                new GlassCubeVertex(new DX.Vector3(-0.5f,  0.5f,  0.5f), new DX.Vector2(0,       0)),
                new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector2(1.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f,  0.5f), new DX.Vector2(0.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(-0.5f,  0.5f, -0.5f), new DX.Vector2(1.0f, 0.0f)),

                // Top face.
                new GlassCubeVertex(new DX.Vector3(-0.5f,  0.5f,  0.5f), new DX.Vector2(0,       0)),
                new GlassCubeVertex(new DX.Vector3(0.5f,   0.5f, -0.5f), new DX.Vector2(1.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(-0.5f,  0.5f, -0.5f), new DX.Vector2(0.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(0.5f,   0.5f,  0.5f), new DX.Vector2(1.0f, 0.0f)),

                // Bottom face.
                new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f, -0.5f), new DX.Vector2(0,       0)),
                new GlassCubeVertex(new DX.Vector3(0.5f,  -0.5f,  0.5f), new DX.Vector2(1.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(-0.5f, -0.5f,  0.5f), new DX.Vector2(0.0f, 1.0f)),
                new GlassCubeVertex(new DX.Vector3(0.5f,  -0.5f, -0.5f), new DX.Vector2(1.0f, 0.0f))
            };

            ushort[] indices =
            {
                8,   9, 10,  8, 11,  9,
                12, 13, 14, 12, 15, 13,
                4,   5,  6,  4,  7,  5,
                16, 17, 18, 16, 19, 17,
                20, 21, 22, 20, 23, 21,
                0,   1,  2,  0,  3, 1
            };

            // Create our index buffer and vertex buffer and populate with our cube data.
            using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(indices))
                using (var vertexPtr = GorgonNativeBuffer <GlassCubeVertex> .Pin(vertices))
                {
                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("GlassCube Index Buffer")
                    {
                        Usage           = ResourceUsage.Immutable,
                        IndexCount      = indices.Length,
                        Use16BitIndices = true
                    },
                                                        indexPtr);

                    VertexBuffer = new GorgonVertexBufferBindings(inputLayout)
                    {
                        [0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics,
                                                                           vertices.Length,
                                                                           ResourceUsage.Immutable,
                                                                           initialData: vertexPtr,
                                                                           bufferName: "GlassCube Vertex Buffer")
                    };
                }
        }
コード例 #21
0
ファイル: Sphere.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Initializes a new instance of the <see cref="Sphere" /> class.
        /// </summary>
        /// <param name="graphics">The graphics interface used to create the buffers for this object.</param>
        /// <param name="inputLayout">The input layout for the vertices in this mesh.</param>
        /// <param name="radius">Radius of the sphere</param>
        /// <param name="textureOffset">Offset of the texture.</param>
        /// <param name="textureScale">Scale of the texture.</param>
        /// <param name="ringCount">Number of rings in the sphere.</param>
        /// <param name="segmentCount">Number of segments in the sphere.</param>
        public Sphere(GorgonGraphics graphics,
                      GorgonInputLayout inputLayout,
                      float radius,
                      DX.Vector2 textureOffset,
                      DX.Size2F textureScale,
                      int ringCount    = 8,
                      int segmentCount = 16)
            : base(inputLayout)
        {
            ushort index       = 0; // Current index.
            int    vertexIndex = 0; // Current vertex index.
            int    indexIndex  = 0; // Current index array index.

            float deltaRingAngle = ((float)System.Math.PI) / ringCount;
            float deltaSegAngle  = (((float)System.Math.PI) * 2.0f) / segmentCount;

            // Calculate number of vertices and indices required for our sphere.
            int vertexCount = (ringCount + 1) * (segmentCount + 1);
            int indexCount  = 6 * ringCount * (segmentCount + 1);

            Vertices = new BoingerVertex[vertexCount];
            Indices  = new ushort[indexCount];

            Radius = radius;

            // Build our sphere.
            for (int ring = 0; ring <= ringCount; ring++)
            {
                float angle    = deltaRingAngle * ring;
                float ringSin  = angle.Sin();
                var   position = new DX.Vector3(0, angle.Cos() * radius, 0);

                for (int segment = 0; segment <= segmentCount; segment++)
                {
                    var   textureDelta = new DX.Vector2(1.0f - (segment / (float)segmentCount), 1.0f - (ring / (float)ringCount));
                    float segmentAngle = deltaSegAngle * segment;

                    position.X = ringSin * segmentAngle.Sin() * radius;
                    position.Z = ringSin * segmentAngle.Cos() * radius;

                    // Create the vertex.
                    textureDelta.X *= textureScale.Width;
                    textureDelta.Y *= textureScale.Height;
                    textureDelta.X += textureOffset.X;
                    textureDelta.Y += textureOffset.Y;

                    Vertices[vertexIndex++] = new BoingerVertex(
                        position,
                        textureDelta
                        );

                    // Add the indices and skip the last ring.
                    if (ring == ringCount)
                    {
                        continue;
                    }

                    Indices[indexIndex++] = (ushort)(index + segmentCount + 1);
                    Indices[indexIndex++] = index;
                    Indices[indexIndex++] = (ushort)(index + segmentCount);
                    Indices[indexIndex++] = (ushort)(index + segmentCount + 1);
                    Indices[indexIndex++] = (ushort)(index + 1);
                    Indices[indexIndex++] = index;
                    index++;
                }
            }

            // Copy the above vertex/index data into a vertex and index buffer so we can render our sphere.
            using (var indexPtr = GorgonNativeBuffer <ushort> .Pin(Indices))
                using (var vertexPtr = GorgonNativeBuffer <BoingerVertex> .Pin(Vertices))
                {
                    VertexBufferBindings[0] = GorgonVertexBufferBinding.CreateVertexBuffer(graphics,
                                                                                           new GorgonVertexBufferInfo("Sphere Vertex Buffer")
                    {
                        SizeInBytes = Vertices.Length * BoingerVertex.Size,
                        Usage       = ResourceUsage.Immutable
                    },
                                                                                           vertexPtr);
                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo("Sphere Index Buffer")
                    {
                        Usage      = ResourceUsage.Immutable,
                        IndexCount = Indices.Length
                    },
                                                        indexPtr);
                }
        }
コード例 #22
0
ファイル: Mesh.cs プロジェクト: ishkang/Gorgon
        /// <summary>
        /// Function to calculate tangent information for bump mapping.
        /// </summary>
        /// <param name="vertexData">Buffer holding the vertices.</param>
        /// <param name="indexData">Buffer holding the indices.</param>
        protected void CalculateTangents(GorgonNativeBuffer <Vertex3D> vertexData, GorgonNativeBuffer <int> indexData)
        {
            var biTanData   = new DX.Vector3[VertexCount];
            var tanData     = new DX.Vector3[VertexCount];
            int indexOffset = 0;

            for (int i = 0; i < TriangleCount; ++i)
            {
                int index1 = indexData[indexOffset++];

                // If we hit a strip-restart index, then skip to the next index.
                if ((PrimitiveType == PrimitiveType.TriangleStrip) &&
                    (index1 < 0))
                {
                    index1 = indexData[indexOffset++];
                }

                int index2 = indexData[indexOffset++];
                int index3 = indexData[indexOffset++];

                Vertex3D vertex1 = vertexData[index1];
                Vertex3D vertex2 = vertexData[index2];
                Vertex3D vertex3 = vertexData[index3];

                DX.Vector4.Subtract(ref vertex2.Position, ref vertex1.Position, out DX.Vector4 deltaPos1);

                DX.Vector4.Subtract(ref vertex3.Position, ref vertex1.Position, out DX.Vector4 deltaPos2);

                DX.Vector2.Subtract(ref vertex2.UV, ref vertex1.UV, out DX.Vector2 deltaUV1);
                DX.Vector2.Subtract(ref vertex3.UV, ref vertex1.UV, out DX.Vector2 deltaUV2);

                float denom = ((deltaUV1.X * deltaUV2.Y) - (deltaUV1.Y * deltaUV2.X));
                float r     = 0.0f;

                if (!denom.EqualsEpsilon(0))
                {
                    r = 1.0f / denom;
                }

                var tangent = new DX.Vector3(((deltaUV2.Y * deltaPos1.X) - (deltaUV1.Y * deltaPos2.X)) * r,
                                             ((deltaUV2.Y * deltaPos1.Y) - (deltaUV1.Y * deltaPos2.Y)) * r,
                                             ((deltaUV2.Y * deltaPos1.Z) - (deltaUV1.Y * deltaPos2.Z)) * r);

                var biTangent = new DX.Vector3(((deltaUV1.X * deltaPos2.X) - (deltaUV2.X * deltaPos1.X)) * r,
                                               ((deltaUV1.X * deltaPos2.Y) - (deltaUV2.X * deltaPos1.Y)) * r,
                                               ((deltaUV1.X * deltaPos2.Z) - (deltaUV2.X * deltaPos1.Z)) * r);

                DX.Vector3.Add(ref tanData[index1], ref tangent, out tanData[index1]);
                DX.Vector3.Add(ref tanData[index2], ref tangent, out tanData[index2]);
                DX.Vector3.Add(ref tanData[index3], ref tangent, out tanData[index3]);

                DX.Vector3.Add(ref biTanData[index1], ref biTangent, out biTanData[index1]);
                DX.Vector3.Add(ref biTanData[index2], ref biTangent, out biTanData[index2]);
                DX.Vector3.Add(ref biTanData[index3], ref biTangent, out biTanData[index3]);
            }

            for (int i = 0; i < VertexCount; ++i)
            {
                Vertex3D vertex = vertexData[i];


                DX.Vector3.Dot(ref vertex.Normal, ref tanData[i], out float dot);
                DX.Vector3.Multiply(ref vertex.Normal, dot, out DX.Vector3 tangent);
                DX.Vector3.Subtract(ref tanData[i], ref tangent, out tangent);
                DX.Vector3.Normalize(ref tangent, out tangent);

                DX.Vector3.Cross(ref vertex.Normal, ref tanData[i], out DX.Vector3 cross);
                DX.Vector3.Dot(ref cross, ref biTanData[i], out dot);

                vertexData[i] = new Vertex3D
                {
                    Position = vertex.Position,
                    Normal   = vertex.Normal,
                    UV       = vertex.UV,
                    Tangent  = new DX.Vector4(tangent, dot < 0.0f ? -1.0f : 1.0f)
                };
            }
        }
コード例 #23
0
        /// <summary>
        /// Function to perform the copying of image data into the buffer.
        /// </summary>
        /// <param name="reader">A reader used to read the data from the source stream.</param>
        /// <param name="image">Image data.</param>
        /// <param name="conversionFlags">Flags used to convert the image.</param>
        private void CopyImageData(GorgonBinaryReader reader, IGorgonImage image, TGAConversionFlags conversionFlags)
        {
            // TGA only supports 1 array level, and 1 mip level, so we only need to get the first buffer.
            IGorgonImageBuffer buffer = image.Buffers[0];

            // Determine how large a row is, in bytes.
            var formatInfo = new GorgonFormatInfo(image.Format);

            GorgonPitchLayout srcPitch = (conversionFlags & TGAConversionFlags.Expand) == TGAConversionFlags.Expand
                                             ? new GorgonPitchLayout(image.Width * 3, image.Width * 3 * image.Height)
                                             : formatInfo.GetPitchForFormat(image.Width, image.Height);

            unsafe
            {
                // Otherwise, allocate a buffer for conversion.
                byte *destPtr = (byte *)buffer.Data;

                // Adjust destination for inverted axes.
                if ((conversionFlags & TGAConversionFlags.InvertX) == TGAConversionFlags.InvertX)
                {
                    destPtr += buffer.PitchInformation.RowPitch - formatInfo.SizeInBytes;
                }

                if ((conversionFlags & TGAConversionFlags.InvertY) != TGAConversionFlags.InvertY)
                {
                    destPtr += (image.Height - 1) * buffer.PitchInformation.RowPitch;
                }

                // Used to counter the number of lines to force as opaque.
                int opaqueLineCount = 0;
                // The buffer used to hold an uncompressed scanline.
                GorgonNativeBuffer <byte> lineBuffer = null;

                try
                {
                    for (int y = 0; y < image.Height; y++)
                    {
                        // Indicates that the scanline has an alpha of 0 for the entire run.
                        bool lineHasZeroAlpha;

                        if ((conversionFlags & TGAConversionFlags.RLE) == TGAConversionFlags.RLE)
                        {
                            lineHasZeroAlpha = ReadCompressed(reader, image.Width, destPtr, image.Format, conversionFlags);
                        }
                        else
                        {
                            // Read the current scanline into memory.
                            if (lineBuffer == null)
                            {
                                lineBuffer = new GorgonNativeBuffer <byte>(srcPitch.RowPitch);
                            }

                            reader.ReadRange(lineBuffer, count: srcPitch.RowPitch);

                            lineHasZeroAlpha = ReadUncompressed((byte *)lineBuffer, srcPitch.RowPitch, destPtr, image.Format, conversionFlags);
                        }

                        if ((lineHasZeroAlpha) && ((conversionFlags & TGAConversionFlags.SetOpaqueAlpha) == TGAConversionFlags.SetOpaqueAlpha))
                        {
                            opaqueLineCount++;
                        }

                        // The components of the pixel data in a TGA file need swizzling for 32 bit.
                        if (formatInfo.BitDepth == 32)
                        {
                            ImageUtilities.SwizzleScanline(destPtr,
                                                           buffer.PitchInformation.RowPitch,
                                                           destPtr,
                                                           buffer.PitchInformation.RowPitch,
                                                           image.Format,
                                                           ImageBitFlags.None);
                        }

                        if ((conversionFlags & TGAConversionFlags.InvertY) != TGAConversionFlags.InvertY)
                        {
                            destPtr -= buffer.PitchInformation.RowPitch;
                        }
                        else
                        {
                            destPtr += buffer.PitchInformation.RowPitch;
                        }
                    }
                }
                finally
                {
                    lineBuffer?.Dispose();
                }

                if (opaqueLineCount != image.Height)
                {
                    return;
                }

                // Set the alpha to opaque if we don't have any alpha values (i.e. alpha = 0 for all pixels).
                destPtr = (byte *)buffer.Data;
                for (int y = 0; y < image.Height; y++)
                {
                    ImageUtilities.CopyScanline(destPtr,
                                                buffer.PitchInformation.RowPitch,
                                                destPtr,
                                                buffer.PitchInformation.RowPitch,
                                                image.Format,
                                                ImageBitFlags.OpaqueAlpha);
                    destPtr += buffer.PitchInformation.RowPitch;
                }
            }
        }
コード例 #24
0
        /// <summary>
        /// Function to create a vertex buffer and its binding.
        /// </summary>
        /// <typeparam name="T">The type of data representing a vertex, must be an unmanaged value type.</typeparam>
        /// <param name="graphics">The graphics interface that will create the buffer.</param>
        /// <param name="info">Information about the buffer to create.</param>
        /// <param name="initialData">[Optional] An initial set of vertex data to send to the buffer.</param>
        /// <param name="bindingIndex">[Optional] The index, in vertices, inside the buffer where binding is to begin.</param>
        /// <returns>A new <see cref="GorgonVertexBufferBinding"/>.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="graphics"/>, or the <paramref name="info"/> parameter is <b>null</b>.</exception>
        /// <remarks>
        /// <para>
        /// Use this to quickly create a vertex buffer and its binding based on a known vertex data type.
        /// </para>
        /// <para>
        /// Be aware that the <see cref="VertexBuffer"/> created by this method must be disposed manually after it is no longer of any use.
        /// </para>
        /// </remarks>
        /// <seealso cref="GorgonVertexBuffer"/>
        public static GorgonVertexBufferBinding CreateVertexBuffer <T>(GorgonGraphics graphics, IGorgonVertexBufferInfo info, GorgonNativeBuffer <T> initialData = null, int bindingIndex = 0)
            where T : unmanaged
        {
            if (graphics == null)
            {
                throw new ArgumentNullException(nameof(graphics));
            }

            if (info == null)
            {
                throw new ArgumentNullException(nameof(info));
            }

            var buffer     = new GorgonVertexBuffer(graphics, info, initialData?.Cast <byte>());
            int vertexSize = Unsafe.SizeOf <T>();

            return(new GorgonVertexBufferBinding(buffer, vertexSize, bindingIndex * vertexSize));
        }
コード例 #25
0
        /// <summary>
        /// Function to persist a <see cref="IGorgonImage"/> to a stream.
        /// </summary>
        /// <param name="imageData">A <see cref="IGorgonImage"/> to persist to the stream.</param>
        /// <param name="stream">The stream that will receive the image data.</param>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="stream"/>, or the <paramref name="imageData"/> parameter is <b>null</b>.</exception>
        /// <exception cref="ArgumentEmptyException">Thrown when the <paramref name="stream"/> is read only.</exception>
        /// <exception cref="NotSupportedException">Thrown when the image data in the stream has a pixel format that is unsupported by the codec.</exception>
        /// <remarks>
        /// <para>
        /// When persisting image data via a codec, the image must have a format that the codec can recognize. This list of supported formats is provided by the <see cref="SupportedPixelFormats"/>
        /// property. Applications may convert their image data a supported format before saving the data using a codec.
        /// </para>
        /// </remarks>
        public override void SaveToStream(IGorgonImage imageData, Stream stream)
        {
            // Ensure that we can actually read this format.  We do not perform total pixel conversion on behalf of the user, they are responsible for that.
            // We will, however, support swizzling and pixel compression (e.g. 32 -> 24 bit).
            if (Array.IndexOf(_supportedFormats, imageData.Format) == -1)
            {
                throw new NotSupportedException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, imageData.Format));
            }

            using (var writer = new GorgonBinaryWriter(stream, true))
            {
                // Write the header for the file before we dump the file contents.
                TgaHeader header = GetHeader(imageData, out TGAConversionFlags conversionFlags);

                GorgonPitchLayout destPitch;

                if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                {
                    destPitch = new GorgonPitchLayout(imageData.Width * 3, imageData.Width * 3 * imageData.Height);
                }
                else
                {
                    var formatInfo = new GorgonFormatInfo(imageData.Format);
                    destPitch = formatInfo.GetPitchForFormat(imageData.Width, imageData.Height);
                }

                GorgonPitchLayout srcPitch = imageData.Buffers[0].PitchInformation;

                // If the two pitches are equal and we have no conversion requirements, then just write out the buffer.
                if ((destPitch == srcPitch) && (conversionFlags == TGAConversionFlags.None))
                {
                    writer.WriteValue(ref header);
                    writer.WriteRange(imageData.Buffers[0].Data, count: srcPitch.SlicePitch);
                    return;
                }

                unsafe
                {
                    // Get the pointer to the first mip/array/depth level.
                    byte *srcPointer = (byte *)imageData.Buffers[0].Data;
                    var   lineBuffer = new GorgonNativeBuffer <byte>(srcPitch.RowPitch);

                    try
                    {
                        // Persist the working buffer to the stream.
                        writer.WriteValue(ref header);

                        // Write out each scan line.
                        for (int y = 0; y < imageData.Height; y++)
                        {
                            byte *destPtr = (byte *)lineBuffer;

                            if ((conversionFlags & TGAConversionFlags.RGB888) == TGAConversionFlags.RGB888)
                            {
                                ImageUtilities.Compress24BPPScanLine(srcPointer,
                                                                     srcPitch.RowPitch,
                                                                     destPtr,
                                                                     destPitch.RowPitch,
                                                                     (conversionFlags & TGAConversionFlags.Swizzle) == TGAConversionFlags.Swizzle);
                            }
                            else if ((conversionFlags & TGAConversionFlags.Swizzle) == TGAConversionFlags.Swizzle)
                            {
                                ImageUtilities.SwizzleScanline(srcPointer, srcPitch.RowPitch, destPtr, destPitch.RowPitch, imageData.Format, ImageBitFlags.None);
                            }
                            else
                            {
                                ImageUtilities.CopyScanline(srcPointer, srcPitch.RowPitch, destPtr, destPitch.RowPitch, imageData.Format, ImageBitFlags.None);
                            }

                            srcPointer += srcPitch.RowPitch;

                            writer.WriteRange(lineBuffer, count: destPitch.RowPitch);
                        }
                    }
                    finally
                    {
                        lineBuffer?.Dispose();
                    }
                }
            }
        }
コード例 #26
0
        /// <summary>
        /// Function to build the Icosphere.
        /// </summary>
        /// <param name="graphics">Graphics interface to use.</param>
        /// <param name="radius">Radius of the sphere.</param>
        /// <param name="tesselation">Tessellation factor for the sphere.</param>
        /// <param name="textureCoordinates">Texture coordinate offset and scale.</param>
        private void BuildSphere(GorgonGraphics graphics, float radius, int tesselation, DX.RectangleF textureCoordinates)
        {
            GetBaseVertices();
            List <int[]> indices = GetBaseIndices();

            for (int i = 0; i < tesselation; ++i)
            {
                var subIndices = new List <int[]>();

                foreach (int[] index in indices)
                {
                    int index0 = GetMiddlePoint(index[0], index[1]);
                    int index1 = GetMiddlePoint(index[1], index[2]);
                    int index2 = GetMiddlePoint(index[2], index[0]);

                    subIndices.Add(new []
                    {
                        index[0],
                        index0,
                        index2
                    });

                    subIndices.Add(new[]
                    {
                        index[1],
                        index1,
                        index0
                    });


                    subIndices.Add(new[]
                    {
                        index[2],
                        index2,
                        index1
                    });

                    subIndices.Add(new[]
                    {
                        index0,
                        index1,
                        index2
                    });
                }

                indices = subIndices;
                _cachedSplits.Clear();
            }

            // Perform texture coordinate calculations and vertex/normal transformations.
            const float piRecip  = 1.0f / (float)System.Math.PI;
            const float pi2Recip = 1.0f / (2.0f * (float)System.Math.PI);

            // Final list.
            var vertexList = new List <Vertex3D>();
            var indexList  = new List <int>();

            foreach (DX.Vector3 vector in _vertices)
            {
                DX.Vector3 position = vector;
                DX.Vector3 normal   = position;
                DX.Vector2 uv       = DX.Vector2.Zero;

                uv.X = ((0.5f - (position.X.ATan(position.Z) * pi2Recip)) * textureCoordinates.Width) + textureCoordinates.X;
                uv.Y = ((0.5f - (position.Y.ASin() * piRecip)) * textureCoordinates.Height) + textureCoordinates.Y;

                DX.Vector3.Multiply(ref position, radius, out position);
                DX.Vector3.TransformCoordinate(ref position, ref _orientation, out position);
                DX.Vector3.TransformCoordinate(ref normal, ref _orientation, out normal);
                normal.Normalize();

                vertexList.Add(new Vertex3D
                {
                    Position = new DX.Vector4(position, 1.0f),
                    Normal   = normal,
                    UV       = uv
                });
            }

            foreach (int[] index in indices)
            {
                for (int j = 0; j < 3; ++j)
                {
                    indexList.Add(index[j]);
                }
            }

            FixSeam(vertexList, indexList);

            using (var vertexData = GorgonNativeBuffer <Vertex3D> .Pin(vertexList.ToArray()))
                using (var indexData = GorgonNativeBuffer <int> .Pin(indexList.ToArray()))
                {
                    VertexCount   = vertexList.Count;
                    IndexCount    = indexList.Count;
                    TriangleCount = IndexCount / 3;

                    CalculateTangents(vertexData, indexData);

                    VertexBuffer = new GorgonVertexBuffer(graphics,
                                                          new GorgonVertexBufferInfo("IcoSphereVertexBuffer")
                    {
                        SizeInBytes = vertexData.SizeInBytes,
                        Usage       = ResourceUsage.Immutable
                    },
                                                          vertexData.Cast <byte>());
                    IndexBuffer = new GorgonIndexBuffer(graphics,
                                                        new GorgonIndexBufferInfo
                    {
                        Usage           = ResourceUsage.Immutable,
                        Use16BitIndices = false,
                        IndexCount      = IndexCount
                    },
                                                        indexData);
                }
        }
コード例 #27
0
ファイル: Sphere.cs プロジェクト: hammerforgegames/Gorgon
        /// <summary>
        /// Function to create the vertex data for the sphere.
        /// </summary>
        /// <param name="vertexData">Pointer to the buffer that will hold the vertex data.</param>
        /// <param name="indexData">Pointer to the buffer that will hold the index data.</param>
        /// <param name="radius">Radius of the sphere.</param>
        /// <param name="textureCoordinates">Texture coordinates for the sphere.</param>
        /// <param name="ringCount">Number of rings in the sphere.</param>
        /// <param name="segmentCount">Number of segments in the sphere.</param>
        private void GetVertices(GorgonNativeBuffer <Vertex3D> vertexData,
                                 GorgonNativeBuffer <int> indexData,
                                 float radius,
                                 RectangleF textureCoordinates,
                                 int ringCount,
                                 int segmentCount)
        {
            int   index          = 0; // Current index.
            int   vertexOffset   = 0;
            int   indexOffset    = 0;
            float deltaRingAngle = ((float)System.Math.PI) / ringCount;
            float deltaSegAngle  = (((float)System.Math.PI) * 2.0f) / segmentCount;

            Radius = radius;

            // Build our sphere.
            for (int ring = 0; ring <= ringCount; ring++)
            {
                float ringAngle = ring * deltaRingAngle;
                radius = ringAngle.Sin() * 0.5f * Radius;
                float radiusY = ringAngle.Cos() * Radius * 0.5f;

                for (int segment = 0; segment <= segmentCount; segment++)
                {
                    var   textureDelta = new DX.Vector2(1.0f - (segment / (float)segmentCount), ring / (float)ringCount);
                    float segmentAngle = deltaSegAngle * segment;

                    var position = new DX.Vector3(radius * segmentAngle.Sin(), radiusY, radius * segmentAngle.Cos());


                    DX.Vector3.Multiply(ref position, 2.0f, out DX.Vector3 normal);
                    DX.Vector3.TransformCoordinate(ref position, ref _orientation, out position);
                    DX.Vector3.TransformCoordinate(ref normal, ref _orientation, out normal);
                    normal.Normalize();

                    // Create the vertex.
                    textureDelta.X *= textureCoordinates.Width;
                    textureDelta.Y *= textureCoordinates.Height;
                    textureDelta.X += textureCoordinates.X;
                    textureDelta.Y += textureCoordinates.Y;

                    vertexData[vertexOffset++] = new Vertex3D
                    {
                        Position = new DX.Vector4(position, 1.0f),
                        UV       = textureDelta,
                        Normal   = normal
                    };

                    // Add the indices and skip the last ring.
                    if (ring == ringCount)
                    {
                        continue;
                    }

                    indexData[indexOffset++] = (index + segmentCount + 1);
                    indexData[indexOffset++] = index;
                    indexData[indexOffset++] = (index + segmentCount);

                    indexData[indexOffset++] = (index + segmentCount + 1);
                    indexData[indexOffset++] = (index + 1);
                    indexData[indexOffset++] = index;
                    index++;
                }
            }
        }
コード例 #28
0
        /// <summary>
        /// Function to convert the image data into a premultiplied format.
        /// </summary>
        /// <param name="baseImage">The image to convert.</param>
        /// <returns>A <see cref="IGorgonImage"/> containing the image data with the premultiplied alpha pixel data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="baseImage"/> is <b>null</b>.</exception>
        /// <exception cref="ArgumentException">Thrown when image format is compressed.</exception>
        /// <remarks>
        /// <para>
        /// Use this to convert an image to a premultiplied format. This takes each Red, Green and Blue element and multiplies them by the Alpha element.
        /// </para>
        /// <para>
        /// If the image does not contain alpha then the method will return right away and no alterations to the image will be performed.
        /// </para>
        /// </remarks>
        public static IGorgonImage ConvertToPremultipliedAlpha(this IGorgonImage baseImage)
        {
            IGorgonImage newImage = null;
            GorgonNativeBuffer <byte> imageData = null;

            if (baseImage == null)
            {
                throw new ArgumentNullException(nameof(baseImage));
            }

            if (!baseImage.FormatInfo.HasAlpha)
            {
                return(baseImage);
            }

            if (baseImage.FormatInfo.IsCompressed)
            {
                throw new ArgumentException(string.Format(Resources.GORIMG_ERR_FORMAT_NOT_SUPPORTED, baseImage.Format), nameof(baseImage));
            }

            try
            {
                var cloneImageInfo = new GorgonImageInfo(baseImage)
                {
                    HasPreMultipliedAlpha = true
                };
                imageData = new GorgonNativeBuffer <byte>(baseImage.ImageData.Length);
                baseImage.ImageData.CopyTo(imageData);

                unsafe
                {
                    newImage = new GorgonImage(cloneImageInfo, new GorgonReadOnlyPointer((void *)imageData, imageData.SizeInBytes));

                    int arrayOrDepth = newImage.ImageType == ImageType.Image3D ? newImage.Depth : newImage.ArrayCount;

                    for (int mip = 0; mip < newImage.MipCount; ++mip)
                    {
                        for (int i = 0; i < arrayOrDepth; ++i)
                        {
                            IGorgonImageBuffer buffer = newImage.Buffers[mip, i];
                            byte *ptr      = (byte *)buffer.Data;
                            int   rowPitch = buffer.PitchInformation.RowPitch;

                            for (int y = 0; y < buffer.Height; ++y)
                            {
                                ImageUtilities.SetPremultipliedScanline(ptr, rowPitch, ptr, rowPitch, buffer.Format);
                                ptr += rowPitch;
                            }
                        }
                    }
                }

                newImage.CopyTo(baseImage);

                return(baseImage);
            }
            finally
            {
                imageData?.Dispose();
                newImage?.Dispose();
            }
        }
コード例 #29
0
        /// <summary>
        /// Function to generate a new mip map chain.
        /// </summary>
        /// <param name="baseImage">The image which will have its mip map chain updated.</param>
        /// <param name="mipCount">The number of mip map levels.</param>
        /// <param name="filter">[Optional] The filter to apply when copying the data from one mip level to another.</param>
        /// <returns>A <see cref="IGorgonImage"/> containing the updated mip map data.</returns>
        /// <exception cref="ArgumentNullException">Thrown when the <paramref name="baseImage"/> parameter is <b>null</b>.</exception>
        /// <remarks>
        /// <para>
        /// This method will generate a new mip map chain for the <paramref name="mipCount"/>. If the current number of mip maps is not the same as the requested number, then the image buffer will be
        /// adjusted to use the requested number of mip maps. If 0 is passed to <paramref name="mipCount"/>, then a full mip map chain is generated.
        /// </para>
        /// <para>
        /// Note that the <paramref name="mipCount"/> may not be honored depending on the current width, height, and depth of the image. Check the width, height and/or depth property on the returned
        /// <see cref="IGorgonImage"/> to determine how many mip levels were actually generated.
        /// </para>
        /// </remarks>
        public static IGorgonImage GenerateMipMaps(this IGorgonImage baseImage, int mipCount, ImageFilter filter = ImageFilter.Point)
        {
            if (baseImage == null)
            {
                throw new ArgumentNullException(nameof(baseImage));
            }

            int maxMips = GorgonImage.CalculateMaxMipCount(baseImage);

            // If we specify 0, then generate a full chain.
            if ((mipCount <= 0) || (mipCount > maxMips))
            {
                mipCount = maxMips;
            }

            // If we don't have any mip levels, then return the image as-is.
            if (mipCount < 2)
            {
                return(baseImage);
            }

            var destSettings = new GorgonImageInfo(baseImage)
            {
                MipCount = mipCount
            };

            var newImage = new GorgonImage(destSettings);
            var wic      = new WicUtilities();

            try
            {
                // Copy the top mip level from the source image to the dest image.
                for (int array = 0; array < baseImage.ArrayCount; ++array)
                {
                    GorgonNativeBuffer <byte> buffer = newImage.Buffers[0, array].Data;
                    int size = buffer.SizeInBytes;
                    baseImage.Buffers[0, array].Data.CopyTo(buffer, count: size);
                }

                // If we have 4 bits per channel, then we need to convert to 8 bit per channel to make WIC happy.
                if (baseImage.Format == BufferFormat.B4G4R4A4_UNorm)
                {
                    newImage.ConvertToFormat(BufferFormat.R8G8B8A8_UNorm);
                }

                wic.GenerateMipImages(newImage, filter);

                // Convert back if we asked for 4 bit per channel.
                if (baseImage.Format == BufferFormat.B4G4R4A4_UNorm)
                {
                    newImage.ConvertToFormat(BufferFormat.B4G4R4A4_UNorm);
                }

                newImage.CopyTo(baseImage);
                return(baseImage);
            }
            finally
            {
                newImage.Dispose();
                wic.Dispose();
            }
        }