Графические примитивы

Последнее обновление: 14.11.2015

При создании трехмерного объекта в прошлой теме мы использовали треугольник. Треугольник является базовым элементом, из которого создаются все остальные трехмерные объекты. Например, для создания прямоугольника нам потребуется два треугольника, для создания куба - 6 прямоугольников и так далее.

Но по факту мы имеем дело не просто с треугольником, а с определенным графическим примитивом, который определяется через перечисление PrimitiveType. Выбор примитива указывает, как будут соединяться вершины в буфере вершин, который передается графическому устройству. В MonoGame есть следующие виду графических примитивов:

  • PrimitiveType.LineList: список линий, по всем вершинам строятся замкнутые линии

  • PrimitiveType.LineStrip: лента линий. Все вершины соединяются одной линией

  • PrimitiveType.TriangleList: список треугольников, из верши создаются замкнутые треугольники

  • PrimitiveType.TriangleStrip: лента треугольников, все вершины последовательно соединяются в треугольники

Рассмотрим се эти примитивы на примере:

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;

namespace First3DGame
{
    public class Game1 : Game
    {
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;

        Matrix projectionMatrix;
        Matrix viewMatrix;
        Matrix worldMatrix;

        VertexPositionColor[] triangleVertices;
        VertexBuffer vertexBuffer;

        BasicEffect effect;

        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";
        }

        protected override void Initialize()
        {
            viewMatrix = Matrix.CreateLookAt(new Vector3(0, 0, 6), Vector3.Zero, Vector3.Up);

            projectionMatrix = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4,
                (float)Window.ClientBounds.Width /(float)Window.ClientBounds.Height,
                1, 100);

            worldMatrix = Matrix.CreateWorld(new Vector3(0f, 0f, 0f), new Vector3(0, 0, -1), Vector3.Up);

            // создаем набор вершин
            triangleVertices = new VertexPositionColor[4];
            triangleVertices[0] = new VertexPositionColor(new Vector3(-1, 1, 0), Color.Red);
            triangleVertices[1] = new VertexPositionColor(new Vector3(1, 1, 0), Color.Green);
            triangleVertices[2] = new VertexPositionColor(new Vector3(-1, -1, 0), Color.Blue);
            triangleVertices[3] = new VertexPositionColor(new Vector3(1, -1, 0), Color.Yellow);
            
            vertexBuffer = new VertexBuffer(GraphicsDevice, typeof(VertexPositionColor),
                triangleVertices.Length, BufferUsage.None);
            vertexBuffer.SetData(triangleVertices);
            
            effect = new BasicEffect(GraphicsDevice);
            effect.VertexColorEnabled = true;

            RasterizerState rasterizerState = new RasterizerState();
            rasterizerState.CullMode = CullMode.None;
            GraphicsDevice.RasterizerState = rasterizerState;

            base.Initialize();
        }
        
        protected override void LoadContent()
        {
            spriteBatch = new SpriteBatch(GraphicsDevice);
        }

        protected override void UnloadContent()
        { }
        
        protected override void Update(GameTime gameTime)
        {
            if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed || 
                Keyboard.GetState().IsKeyDown(Keys.Escape))
                Exit();

            base.Update(gameTime);
        }
        
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.CornflowerBlue);
            
            effect.World = worldMatrix;
            effect.View = viewMatrix;
            effect.Projection = projectionMatrix;

            GraphicsDevice.SetVertexBuffer(vertexBuffer);
            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Apply();
                // отрисовка примитива
                GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
                    (PrimitiveType.LineList, triangleVertices, 0, 2);
            }

            base.Draw(gameTime);
        }
    }
}

Здесь мы определяем четыре вершины в буфере вершин. А в качестве примитива использован LineStrip:

// отрисовка примитива
GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
        (PrimitiveType.LineList, triangleVertices, 0, 2);

Этот примитив создает набор замкнутых линий. Для создания линии нужно две вершины. Поэтому из четырех вершин в буфере, которые у нас есть, мы получим две изолированные линии. То есть первая и вторая вершина составят первую линию, а третья и четвертая - вторую линию. Поэтому в метод GraphicsDevice.DrawUserPrimitives в качестве последнего параметра передается число 2 - число отрисовываемых линий. Больше этого числа, например, 3, мы не можем указать, так как у нас нет столько вершин для создания изолированных линий. Можно лишь указать меньшее число, если нам надо меньше линий.

LineList в MonoGame

Теперь изменим тип примитива при выводе на LineStrip (вся остальная часть программы остается той же):

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
        (PrimitiveType.LineStrip, triangleVertices, 0, 3);

LineStrip последовательно соединяет все вершины в связанные линии, то есть первая вершина соединяется во второй, вторая с третьей, третья с четвертой. И, таким образом, образуется три линии:

LineStrip в MonoGame

Опять же в качестве последнего параметра мы не можем передать число большее, чем максимально возможное количество линий, то есть три в данном случае.

Изменим тип примитива на TriangleStrip:

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
        (PrimitiveType.TriangleStrip, triangleVertices, 0, 2);

TriangleStrip последовательно соединяет вершины в соединенные треугольники. Так, первая соединяется со второй и третьей вершиной, образуя первый треугольник. Вторая вершина соединяется с третьей и четвертой вершинами, образуя второй треугольник. Больше вершин у нас нет, поэтому в данном случае у нас может быть только два треугольника, которые вместе образуют прямоугольник:

TriangleStrip в MonoGame

И последний тип - TriangleList соединяет вершины в замкнутые треугольники. Так, первая соединяется со второй и третьей вершиной, образуя первый треугольник. Четвертая вершина соединяется с пятой и шестой вершинами, образуя второй треугольник. То есть теперь треугольники не соединяются. И поскольку у нас только четыре вершины, то с помощью данного примитива мы можем создать только один треугольник:

GraphicsDevice.DrawUserPrimitives<VertexPositionColor>
        (PrimitiveType.TriangleList, triangleVertices, 0, 1);
TriangleList в MonoGame
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850