Треугольники

Проект triangle1

Для работы не потребуется DirectX SDK но нужно иметь:
1. Visual C# 2010 Express or Visual Studio 2010 Professional
2. XNA Game Studio 4.0
3. DirectX End-User Runtimes

1. Main Menu VS 2010: File → New Project... → Project types: XNA GameStudio 4.0 → Templates: Windows Game (4.0) → Name: triangle1 → Location: C:\temp → Create directory for solution: отключить → OK.
Solution Explorer - triangle1: Удалите файл Program.cs и удалите код Game1.cs.

2. Посмотрите на коллекцию подключенных "References". Должно быть подключено Microsoft.XNA.Framework, Microsoft.XNA.Framework.Game, mscorlib и System.

Game1, Initialize, Update, Draw

напишите следующий код в Game1.cs:

using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
static class Program
{
    static void Main()
    {
        Game1 game = new Game1();
        game.Run();
    }

    public class Game1 : Microsoft.Xna.Framework.Game
    {
        private GraphicsDeviceManager g;
        private VertexBuffer vbuffer;
        private BasicEffect effect;
        private EffectPass pass;
        private float rotAngle = 0f;

        public Game1()
        {
            Window.Title = "3DTriangleAnimation";
            Window.AllowUserResizing = true;
            g = new GraphicsDeviceManager(this);
            g.IsFullScreen = false;
            g.PreferredBackBufferWidth = 300;
            g.PreferredBackBufferHeight = 300;
        }

        protected override void Initialize()
        {
            VertexPositionColor[] v = new VertexPositionColor[3];
            v[0].Position.X = -1f;
            v[0].Position.Y = -1f;
            v[0].Position.Z = 0f;
            v[1].Position.X = 0f;
            v[1].Position.Y = 0f;
            v[1].Position.Z = 0f;
            v[2].Position.X = 1f;
            v[2].Position.Y = -1f;
            v[2].Position.Z = 0f;
            v[0].Color = Color.Blue;
            v[1].Color = Color.Cornsilk;
            v[2].Color = Color.MediumOrchid;
            vbuffer = new VertexBuffer(g.GraphicsDevice, typeof(VertexPositionColor),
                                        3, BufferUsage.WriteOnly);
            vbuffer.SetData<VertexPositionColor>(v);
            effect = new BasicEffect(g.GraphicsDevice);
            //effect.View = Matrix.CreateLookAt( new Vector3(0, 0, 3), Vector3.Zero, Vector3.Up ); 
            //effect.Projection = Matrix.CreatePerspectiveFieldOfView( MathHelper.Pi/4, 1f, 1f, 10f ); 
            effect.VertexColorEnabled = true; pass = effect.CurrentTechnique.Passes[0];
        }

        protected override void Update(GameTime gameTime)
        {
            //g.GraphicsDevice.Vertices[0].SetSource(vbuffer, 0, VertexPositionColor.SizeInBytes);
            g.GraphicsDevice.SetVertexBuffer(vbuffer);
            //g.GraphicsDevice.VertexDeclaration = new VertexDeclaration(g.GraphicsDevice, VertexPositionColor.VertexElements);
            //g.GraphicsDevice.RenderState.CullMode = CullMode.None; 
        }

        protected override void Draw(GameTime gameTime)
        {
            //g.GraphicsDevice.Clear( Color.DarkBlue ); 
            //effect.World = Matrix.CreateRotationY( rotAngle += 0.01f ); 

            effect.CurrentTechnique.Passes[0].Apply();
            //effect.Begin();
            //pass.Begin();
            try
            {
                g.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1);
            }
            catch { }

            //pass.End();
            //effect.End();
        }
    } // end of class Game1 
} // end of class Program

Нажмите DebugStart Without Debugging Ctrl F5. Подергайте края окна.


Изменения: (Start Without Debugging Ctrl F5 после любых изменений)

1. Измените g.PreferredBackBufferWidth и g.PreferredBackBufferHeight с 300 на 600.Окно увеличится при старте.
2. Измените v[1].Position.Y= 0f; на v[1].Position.Y= 1f;.Треугольник равносторонний
3. Измените v[0].Color = Color.Blue; на v[0].Color = Color.DarkGoldenrod;.Левый нижний цвет меняется.
4. Удалив  // вначале  //g.GraphicsDevice.Clear( Color.DarkBlue ); раскомментарьте строку.синий фон
5. Раскомментарьте строку  //g.GraphicsDevice.RenderState.CullMode = CullMode.None;
Раскомментарьте строку //effect.View = ...
Раскомментарьте строку //effect.Projection = ...
Треугольник визуально уменьшается.
6. Раскомментарьте строку //effect.World *= ...Вращение вокруг оси Y

Сохраните все изменения.
Эксперименты: (Восстановите все изменения после каждого эксперимента.)

1. Поставив // перед строкой, закомментарьте код g.GraphicsDevice.RenderState.CullMode = CullMode.None;.The backside of the triangle disappears.
2. Измените значение Z позиции камеры в Vector3(0,0,3) в выражении effect.View=Matrix.CreateLookAt(new Vector3(0, 0,3),Vector3.Zero,Vector3.Up) с 3 на 4, 2, -2, -3.The camera moves on the Z-axis.
3. Измените направление оси Y в  effect.View=Matrix.CreateLookAt(new Vector3(0,0,3),Vector3.Zero,Vector3.Up ) с Vector3.Up на Vector3.Down.Треугольник появляется перевернутым.
4. Измените угол обзора в effect.Projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.Pi/4,1f,1f,10f); с MathHelper.Pi/4 = 45° на МathHelper.Pi/2 = 90°.Треугольник визуально уменьшается.
5. Измените дельту угла в effect.World=Matrix.CreateRotationY(rotAngle+=0.01f); с 0.01f на 0.1f и на 0.003f.Более быстрое или медленное вращение.
6. Измените ось вращения в effect.World=Matrix.CreateRotationY(rotAngle+=0.01f); с CreateRotationY на CreateRotationX.Вращение вокруг оси X.
7. Измените ось вращения в effect.World=Matrix.CreateRotationY(rotAngle+=0.01f); с CreateRotationY на CreateRotationZ.Вращение вокруг оси Z


Три треугольника


Определите 4 новые глобальные переменные в заголовочнике public class Game1 : Microsoft.Xna.Framework.Game сразу после строки float rotationAngle = 0f;:

private Matrix rot = Matrix.CreateRotationY( 0f ); 
private Matrix zoom = Matrix.CreateScale( 0.5f ); 
private Matrix leftshift = Matrix.CreateTranslation( new Vector3( -1f, 0f, 0f ) ); 
private Matrix rightshift = Matrix.CreateTranslation( new Vector3( 1f, 0f, 0f ) );

Измените функцию protected override void Draw( GameTime gameTime )- следующим образом:

protected override void Draw( GameTime gameTime ) { 
            g.GraphicsDevice.Clear(Color.DarkBlue); rot = Matrix.CreateRotationY(rotAngle += 0.01f); //rot = Matrix.CreateFromYawPitchRoll( rotAngle += 0.01f, rotAngle, rotAngle ); effect.World = rot; effect.CurrentTechnique.Passes[0].Apply(); try { g.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); } catch { } effect.World = zoom * rot * leftshift; try { g.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); } catch { } effect.World = zoom * rot * rightshift; try { g.GraphicsDevice.DrawPrimitives(PrimitiveType.TriangleList, 0, 1); } catch { } 
}

Жмите DebugStart Without Debugging Ctrl F5. Подергайте края окна.
Эксперименты: (Восстанавливайте код после каждого эксперимента.)

1. Измените zoom- фактор в Matrix zoom = Matrix.CreateScale(0.5f); с 0.5f на 0.2f и на 1.2f.Уменьшает - Увеличивает треугольники.
2. Измените leftshift левого малого треугольника в Matrix leftshift = Matrix.CreateTranslation(new Vector3(-1f,0f,0f)); с-1f на -1.5f и на -0.5f.Левый треугольник горизонтально сдвигается вдоль оси X.
3. Измените leftshift для левого треугольника в Matrix leftshift = Matrix.CreateTranslation(new Vector3(-1f,0f,0f)); с new Vector3(-1f,0f,0f) на new Vector3(-1f,1f,0f) и на new Vector3(-1f,-1f,0f).Левый треугольник сдвинут вертикально.
4. Измените leftshift в Matrix leftshift = Matrix.CreateTranslation(new Vector3(-1f,0f,0f)); с new Vector3(-1f,0f,0f ) на Vector3(-1f,0f,-2f).Левый треугольник сдвигается назад и визуально уменьшается.
5. Закомментарьте //Matrix.CreateRotationY( rotationAngle );. Раскомментарьте //rot=Matrix.CreateFromYawPitchRoll(rotAngle+=0.01f,rotAngle,rotAngle);. Сохраните эти изменения.Треугольники вращаются одновременно вокруг осей  X, Y и Z.

Сотня треугольников

Добавьте следующее определение в заголовочник класса public class Game1 : Microsoft.Xna.Framework.Game под линией: Matrix rightshift=Matrix.CreateTranslation(new Vector3(1f,0f,0f));:

private const Int32 nTriangles = 100; 
private float[] dx = new float[nTriangles]; 
private float[] dy = new float[nTriangles]; 
private float[] dz = new float[nTriangles]; 
private float[] ax = new float[nTriangles]; 
private float[] ay = new float[nTriangles]; 
private float[] az = new float[nTriangles]; 
private Random r = new Random();

Добавьте следующую инициализацию protected override void Initialize() под строкой: pass = effect.CurrentTechnique.Passes[0];.

for ( int i = 0; i < nTriangles; i++ ) { 
   dx[i] = (float)r.NextDouble() - 0.5f; //random permanent translation dx 
   dy[i] = (float)r.NextDouble() - 0.5f; //random permanent translation dy 
   dz[i] = (float)r.NextDouble() - 0.5f; //random permanent translation dz 
}
g.GraphicsDevice.RenderState.DepthBufferEnable = false; g.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;

Измените функцию protected override void Draw( GameTime gameTime ) следующим образом:

protected override void Draw( GameTime gameTime ) { 
   g.GraphicsDevice.Clear( Color.DarkBlue ); 
   rot = Matrix.CreateFromYawPitchRoll( rotAngle += 0.01f, rotAngle, rotAngle ); 
   effect.Begin(); 
   for ( int i = 0; i < nTriangles; i++ ) { 
      pass.Begin(); 
      leftshift = Matrix.CreateTranslation( dx[i], dy[i], dz[i] ); 
      effect.World = zoom * rot * leftshift; 
      try { 
         g.GraphicsDevice.DrawPrimitives( PrimitiveType.TriangleList, 0, 1 ); 
      } catch {} 
      pass.End(); 
   } 
   effect.End(); 
}

Жмите DebugStart Without Debugging Ctrl F5. Сотни маленьких треугольников танцуют вместе, как рыбки.

Хаос

Измените protected override void Initialize() под строкой: pass = effect.CurrentTechnique.Passes[0]; следующим образом:

for ( int i = 0; i < nTriangles; i++ ) { 
   dx[i] = (float)r.NextDouble() - 0.5f; //random permanent translation dx 
   dy[i] = (float)r.NextDouble() - 0.5f; //random permanent translation dy 
   dz[i] = (float)r.NextDouble() - 0.5f; //random permanent translation dz 
   ax[i] = (float)r.NextDouble(); //random initial pitch rotation angle 
   ay[i] = (float)r.NextDouble(); //random initial yaw rotation angle 
   az[i] = (float)r.NextDouble(); //random initial roll rotation angle 
} 
g.GraphicsDevice.RenderState.DepthBufferEnable = false; 
g.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;

Измените функцию protected override void Draw( GameTime gameTime ) следующим образом:

protected override void Draw( GameTime gameTime ) { 
   g.GraphicsDevice.Clear( Color.DarkBlue ); 
   effect.Begin(); 
   for ( int i = 0; i < nTriangles; i++ ) { 
      pass.Begin(); 
      rot = Matrix.CreateFromYawPitchRoll( ay[i] += 0.01f, ax[i] += 0.01f, az[i] += 0.01f ); 
      leftshift = Matrix.CreateTranslation( dx[i], dy[i], dz[i] ); 
      effect.World = zoom * rot * leftshift; 
      g.GraphicsDevice.DrawPrimitives( PrimitiveType.TriangleList, 0, 1 ); 
      pass.End(); 
   } 
   effect.End(); 
}

Жмите DebugStart Without Debugging Ctrl F5. Сотня маленьких треугольников танцуют, как падающие листы бумаги.

Эксперименты: (Восстанавливайте код после каждого эксперимента)

1. Разрешите  Z-тест и закомментарьте обе строки g.GraphicsDevice.RenderState.DepthBufferEnable = false; и g.GraphicsDevice.RenderState.DepthBufferWriteEnable = false;. Сохраните эти изменения.Новые треугольники не перекрывают старые.
2. Измените константу const Int32 nTriangles = 100; в диапазоне от 10 до 1000.
Меньше или больше треугольников.
3. Поменяйте случайные начальные значения углов вращения pitch+yaw+roll ax[i], ay[i], az[i] внутри конструктора между 0f и 1f.Начальный беспорядок.
4. Поменяйте коэффициент торможения 0.01f внутри Matrix.CreateFromYawPitchRoll или угловы дельты ay[i], ax[i] и az[i] от 0.001f до 0.1f.Меньше - Больше хаоса.
5. Вставьте новую строку под строкой pass.Begin();:
zoom = Matrix.CreateScale( new Vector3( (float)r.NextDouble(), (float)r.NextDouble(), (float)r.NextDouble() ) );.
Суета.

Удачи! :)