powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Программирование [игнор отключен] [закрыт для гостей] / DirectX вращение камеры вокруг центра
32 сообщений из 32, показаны все 2 страниц
DirectX вращение камеры вокруг центра
    #38169234
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здравствуйте! Эта тема продолжение вот этой . Пытаюсь создать класс камеры, где была бы возможность двигать камеру вокруг объекта(в данном случае вокруг центра сферы). В прикрепленном архиве есть проект и само приложение. Проблема заключается в том, что когда я нажимаю кнопки A или D, т.е. в лево и вправо, то куб в центре вращается нормально(точнее камера вокруг него), когда W или S, вверх и вниз, то тоже нормально, но когда после W или S я нажимаю A или D куб куда-то уезжает. Т.е. он начинает двигаться по кругу. И чем больше удерживаешь W или S, тем больше становиться размер круга.
Пример:
1.Нажал D - работает
2.Нажал W - работает
3.Нажал D - уезжает

или вот так

1.Нажал W - работает
2.Нажал D - уезжает.
Т.е. при движении камеры по оси Y что-то сбивается, а что понять не могу. Приведу пример класса камеры и вызов процедуры вращения:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Camera
{
    class Camera
    {
        public enum CameraType
        {
            LANDOBJECT,
            AIRCRAFT
        };

        public CameraType cameraType;
        private Vector3 right = new Vector3(1.0f, 0, 0);
        private Vector3 up = new Vector3(0, 1.0f, 0.0f);
        private Vector3 look = new Vector3(0.0f, 0.0f, 1.0f);
        private Vector3 pos = new Vector3(0, -1.97f, -90.0f);
        float _cam_yaw = 0.0f;
        float _cam_pitch = -0.0f;
        Vector3 center = new Vector3(0, 0, 0);
        Matrix v;

        public Camera()
        {
            cameraType = CameraType.AIRCRAFT;
        }
        public Camera(CameraType _cameraType)
        {
            cameraType = _cameraType;

        }
        public Matrix GetViewMatrix(Matrix v)
        {
            look.Normalize();
            up = Vector3.Cross(look, right);
            up.Normalize();
            right = Vector3.Cross(up, look);
            right.Normalize();

            float x = Vector3.Dot(right, pos);
            float y = Vector3.Dot(up, pos);
            float z = Vector3.Dot(look, pos);
       
            v.M11 = right.X;
            v.M12 = up.X;
            v.M13 = look.X;
            v.M14 = 0.0f;

            v.M21 = right.Y;
            v.M22 = up.Y;
            v.M23 = look.Y  ;
            v.M24 = 0.0f;

            v.M31 = right.Z;
            v.M32 = up.Z;
            v.M33 = look.Z;
            v.M34 = 0.0f;

            v.M41 = -Vector3.Dot(right, pos);
            v.M42 = -Vector3.Dot(up, pos);
            v.M43 = -Vector3.Dot(look, pos);//расстояние по оси Z
            v.M44 = 1.0f;
            return v;
        }       
        private Vector3 rotate(Vector3 point_on_axis, Vector3 dir, float angle, Vector3 point)
        {
            Vector3 r = point - point_on_axis;
            dir.Normalize();
            float a = angle * (float)(Math.PI / 180.0f);
            return point_on_axis + (float)Math.Cos(a) * r + ((1 - (float)Math.Cos(a)) * Vector3.Dot(dir, r)) * dir + (float)Math.Sin(a) * Vector3.Cross(dir, r);           
        }
        
        private float radFromDeg(float angle)
        {
            return angle * (float)(Math.PI / 180);
        }
        public void arcRotate(float x, float y)
        {
            if (x != 0)
            {
                float yaw_diff = x;
                pos = rotate(center, new Vector3(0, 1, 0), yaw_diff, pos);               
               heading(yaw_diff);                
            }
            if (y != 0)
            {
                float pitch_diff = -y;
                pos = rotate(center, right, pitch_diff, pos);
                pitch(pitch_diff);
            }
        }
        public void heading(float angle)// вращение относительно верхнего вектора
        {
            float rad = angle * ((float)Math.PI / 180);
            Matrix t;
            t = Matrix.RotationAxis(up, rad);
             right.TransformCoordinate(t);
             look.TransformCoordinate(t);     
        }
        public void pitch(float angle)// вращение относительно правого вектора
        {
            float rad = angle * ((float)Math.PI / 180);
             Matrix t;
             t = Matrix.RotationAxis(right, rad);
             up.TransformCoordinate(t);
             look.TransformCoordinate(t);
        }    
    }
}



вызов

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            
            switch (e.KeyCode)
            {
                case Keys.W:
                    camera.arcRotate(0, 1);   
                     break;
                case Keys.S:
                     camera.arcRotate(0, -1);                  
                    break;
                case Keys.D:
                    camera.arcRotate(1, 0);                 
                    break;
                case Keys.A:
                    camera.arcRotate(-1, 0);
                    break;                

            }
        }



возможно проблема вот в этой формуле, но как она работает я понять не могу
Код: c#
1.
 point_on_axis + (float)Math.Cos(a) * r + ((1 - (float)Math.Cos(a)) * Vector3.Dot(dir, r)) * dir + (float)Math.Sin(a) * Vector3.Cross(dir, r);           


Подскажите пожалуйста, как решить эту проблему.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38169652
pirovindos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kokon,

Если хочешь двигать камеру по сфере? то придется отказаться от отдельных движений по оси X и по оси Y и крутить всегда в 3D.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38169677
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
и крутить всегда в 3D

а можно поподробнее
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38169702
pirovindos
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Kokon,

Поподробнее - это с картинками и матрицами вращения, потому что проблема не в одной формуле...
1. Нужно определится с системой координат и что меняется при нажатии кнопок.
1.1. Можно взять направляющие углы, pitch и direction подойдут. Но тогда у тебя будет полюса, в которых нельзя пользоваться формулами -= и +=.
Грубо говоря, когда ты пешком проходишь через точку Северного полюса на Земле, то у тебя скачком меняется долгота (direction), а широта сначала увеличивается, а потом уменьшается, хотя ты никуда не прыгал и не менял направление движения.
1.2. Можно взять только 3D координаты камеры и задать стартовое направление на кадре "вверх", и при нажатии кнопок "вращать относительно текущей (а не X или Y) оси, параллельной стороне кадра.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38170138
wvetal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kokon,

В приложении прога с кубиком.
Такой результат ожидаешь? Если да - то я скину исходник(скорее всего это будет уже в пятницу).
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38170176
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wvetal, у меня к сожалению приложение не запускается. выложи пожалуйста исходники. я посмотрю их, может подойдет.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38170473
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wvetal,
на другом компе запустилось. то что надо)))
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38170769
wvetal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kokonwvetal,
на другом компе запустилось. то что надо)))
Тогда выкладываю исходники.
1) тебе достаточно будет только заменить файл Form1.cs в твоем проекте (я его дам отдельно в приложении + там еще будет весь солюшн с моим проектом под VS2005, даю на всякий случай)
2) класс Camera, который у тебя описан в Camera.cs я вообще не использовал.

Файл Form1.cs:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Camera
{
    public partial class Form1 : Form
    {

	//добавил эти переменные
    	private float cam_z = -13;
    	private float cam_y = 0;
    	private float cam_x = 0;
    	private float r = 13;
    	private float ugol = (float)Math.PI/2;
    	private float ugol2 = 0;


        private Device device;
        //private Camera camera = new Camera(); //закомментировал, использоваться не будет
        //private Matrix v; 			//закомментировал, использоваться не будет     
        private VertexBuffer vb = null;
        public Form1()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
            InitializeComponent();
        }

        public void InitializeGraphics()
        {
            PresentParameters pp = new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;
            pp.EnableAutoDepthStencil = true;
            pp.AutoDepthStencilFormat = DepthFormat.D16;
            pp.DeviceWindow = this;
            device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, pp);
            device.RenderState.Ambient = Color.Blue;

            vb = new VertexBuffer(typeof(CustomVertex.PositionColored),
                                 36,
                                 device,
                                 Usage.Dynamic | Usage.WriteOnly,
                                 CustomVertex.PositionColored.Format,
                                 Pool.Default);           
            vb.Created += new EventHandler(vb_Created);
            vb_Created(vb, null);           
        }

        void vb_Created(object sender, EventArgs e)
        {
             VertexBuffer buffer = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = new
                CustomVertex.PositionColored[36];        
            // Задняя грань: треугольник 2-0-1 (невидимая сторона - обход левый)
            verts[0] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Red.ToArgb());
            verts[1] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Red.ToArgb());
            verts[2] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Red.ToArgb());
            // Задняя грань: треугольник 2-1-3 (невидимая сторона - обход левый)
            verts[3] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Red.ToArgb());
            verts[4] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Red.ToArgb());
            verts[5] = new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Red.ToArgb());
            //
            // Передняя грань: треугольник 5-6-4 (лицевая сторона - обход правый)
            verts[6] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Blue.ToArgb());
            verts[7] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Blue.ToArgb());
            verts[8] = new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Blue.ToArgb());
            // Передняя грань: треугольник 5-7-6 (лицевая сторона - обход правый)
            verts[9] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Blue.ToArgb());
            verts[10] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Blue.ToArgb());
            verts[11] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Blue.ToArgb());
            //
            // Верхняя грань: треугольник 0-5-4 (лицевая сторона - обход правый)
            verts[12] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Yellow.ToArgb());
            verts[13] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Yellow.ToArgb());
            verts[14] = new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Yellow.ToArgb());
            // Верхняя грань: треугольник 0-2-5 (лицевая сторона - обход правый)
            verts[15] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Yellow.ToArgb());
            verts[16] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Yellow.ToArgb());
            verts[17] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Yellow.ToArgb());
            //
            // Нижняя грань: треугольник 1-6-7 (невидимая сторона - обход левый)
            verts[18] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Black.ToArgb());
            verts[19] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Black.ToArgb());
            verts[20] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Black.ToArgb());
            // Нижняя грань: треугольник 1-7-3 (невидимая сторона - обход левый)
            verts[21] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Black.ToArgb());
            verts[22] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Black.ToArgb());
            verts[23] = new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Black.ToArgb());
            //
            // Левая грань: треугольник 0-6-1 (невидимая сторона - обход левый)
            verts[24] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Gray.ToArgb());
            verts[25] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Gray.ToArgb());
            verts[26] = new CustomVertex.PositionColored(-1.0F, -1.0F, 1.0F, Color.Gray.ToArgb());
            // Левая грань: треугольник 0-4-6 (невидимая сторона - обход левый)
            verts[27] = new CustomVertex.PositionColored(-1.0F, 1.0F, 1.0F, Color.Gray.ToArgb());
            verts[28] = new CustomVertex.PositionColored(-1.0F, 1.0F, -1.0F, Color.Gray.ToArgb());
            verts[29] = new CustomVertex.PositionColored(-1.0F, -1.0F, -1.0F, Color.Gray.ToArgb());
            //
            // Правая грань: треугольник 2-3-7 (лицевая сторона - обход правый)
            verts[30] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Green.ToArgb());
            verts[31] = new CustomVertex.PositionColored(1.0F, -1.0F, 1.0F, Color.Green.ToArgb());
            verts[32] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Green.ToArgb());
            // Правая грань: треугольник 2-7-5 (лицевая сторона - обход правый)
            verts[33] = new CustomVertex.PositionColored(1.0F, 1.0F, 1.0F, Color.Green.ToArgb());
            verts[34] = new CustomVertex.PositionColored(1.0F, -1.0F, -1.0F, Color.Green.ToArgb());
            verts[35] = new CustomVertex.PositionColored(1.0F, 1.0F, -1.0F, Color.Green.ToArgb());

            // Заполнить вершинный буфер данными треугольников
            buffer.SetData(verts, 0, LockFlags.None);
        }

       

        private void Form1_Load(object sender, EventArgs e)
        {
            

        }
        protected override void OnPaint(PaintEventArgs e)
        {
            device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Aquamarine, 1.0f, 0);
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 100.0f);
            //degree++;
            device.Transform.World = Matrix.Translation(0, 0, 0);
        //    Vector3 camup = new Vector3(0, 0, 1);
        //    Vector3 campos = new Vector3(cam_x, cam_y, cam_z);
            //v = camera.GetViewMatrix(v);			//закомментировал, использоваться не будет
            //device.SetTransform(TransformType.View, v);	//закомментировал, использоваться не будет
            
	    device.Transform.View = Matrix.LookAtLH(new Vector3(cam_x, cam_y, cam_z), new Vector3(0, 0, 0), new Vector3(0, (float)Math.Cos(ugol - (float)Math.PI/2), 0)); //добавил это
	    device.RenderState.Lighting = false;            
            device.RenderState.PointSize = 5.0f;            
            device.BeginScene();
            device.VertexFormat = CustomVertex.PositionColored.Format;
            device.VertexFormat = CustomVertex.PositionColored.Format;
            // Нарисовать треугольник по данным из буфера
            device.SetStreamSource(0, vb, 0);
            device.DrawPrimitives(PrimitiveType.TriangleList, 0, 12);
            device.EndScene();
            device.Present();
            this.Invalidate();        

        }

        private void Form1_Paint(object sender, PaintEventArgs e)
        {
           
        }        
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            
	    //добавил сюда
            switch (e.KeyCode)
            {
                case Keys.W:
          	  //camera.arcRotate(0, 1);
          	  ugol -= 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
        	case Keys.S:
          	  //camera.arcRotate(0, -1);
          	  ugol += 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
        	case Keys.D:
          	  //camera.arcRotate(1, 0);
          	  ugol2 += 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
        	case Keys.A:
          	  //camera.arcRotate(-1, 0);
          	  ugol2 -= 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
                

            }
            //this.Text = "ugol " + ugol.ToString() + " cam_x " + cam_x.ToString() + " cam_y " + cam_y.ToString() + " cam_z " + cam_z.ToString() + " ugol2 " + ugol2.ToString();
        }



    }
}


...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38171143
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wvetal,
большое спасибо. работает
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38171216
wvetal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Kokon,

А какую литературу ты используешь для DirectX и C#?

... и еще... там нажатие клавиш лучше обрабатывать не
Код: c#
1.
private void Form1_KeyDown


а делать через DirectInput
Код: c#
1.
KeyboardState keys = keyb.GetCurrentKeyboardState();
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38171501
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
wvetal,
по с# я видел только одну книгу Тома Миллера. А остальное статьи, книги по с++, а вообще делаю простенький 3D редактор, ну просто для того чтобы не просто так изучать directx, а выполняя конкретную задачу. Так интереснее.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38171866
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Косяк один обнаружил. Когда камера двигается вертикально (кнопки S или W) то получается, что она вращается относительно оси Х и когда она передвигается на 90 град, т.е. смотрит сверху вниз на ось Y мировых координат и если при этом нажимать на A или D тогда камера вращается вокруг оси Y, а выглядит так что куб крутится вокруг своей оси. Т.е. когда мы с боку смотрим на куб, то он правильно поворачивается, а когда сверху, то математически тоже правильно, но выглядит это не так как надо. Получается когда мы смотрим на куб сверху вниз и нажимаем на A или D тогда надо вращаться не вокруг оси Y, а вокруг оси Z. Т.е. определять в каком положении находится камера и в зависимости от этого вращаться вокруг определенных осей. Вот такая фигня. Пока еще не понял как это решить.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38171892
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Хотя наверно это правильно. Посмотрел в 3D редакторах, там тоже самое. Если на сцену сверху вниз смотришь, то она вращается по кругу. Так что это не косяк.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38172288
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:

KokonЭта тема продолжение вот этой .Там и надо было продолжать писать (не закрыто же), тема та же, незачем было новое обсуждение создавать. Ну да ладно, это мелочь.

Kokonвозможно проблема вот в этой формуле, но как она работает я понять не могу
Код: c#
1.
 point_on_axis + (float)Math.Cos(a) * r + ((1 - (float)Math.Cos(a)) * Vector3.Dot(dir, r)) * dir + (float)Math.Sin(a) * Vector3.Cross(dir, r);           

Формулу поворота точки вокруг оси вы скопировали правильно, в ней проблем быть не должно. Если хотите, объясню, как она получена. Вот другие вещи вы скопировали с изменениями, например использовали другую систему координат. Мой код :
Пётр Седов
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
// move_x, move_y можно брать из движений мыши
void arc_rotate(int move_x, int move_y) {
  if (move_x != 0) {
    double yaw_diff = move_x;
    _cam_pos = rotate(/*point_on_axis:*/_arc_rotate_center, /*axis_dir:*/v3(0, 0, 1), yaw_diff, _cam_pos);
    _cam_yaw += yaw_diff;
    calc_cam_axes();
  }
  if (move_y != 0) {
    double pitch_diff = -move_y;
    _cam_pos = rotate(/*point_on_axis:*/_arc_rotate_center, /*axis_dir:*/_cam_right, pitch_diff, _cam_pos);
    _cam_pitch += pitch_diff;
    calc_cam_axes();
  }
  request_paint(); // invalidate
}

Ваш код:
Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
        public void arcRotate(float x, float y)
        {
            if (x != 0)
            {
                float yaw_diff = x;
                pos = rotate(center, new Vector3(0, 1, 0), yaw_diff, pos);               
               heading(yaw_diff);                
            }
            if (y != 0)
            {
                float pitch_diff = -y;
                pos = rotate(center, right, pitch_diff, pos);
                pitch(pitch_diff);
            }
        }

Мой код работает правильно (камера вращается так же, как в 3ds max), но правильность вашего изменённого варианта я уже гарантировать не могу.

2 wvetal:

wvetal
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
...
	    device.Transform.View = Matrix.LookAtLH(new Vector3(cam_x, cam_y, cam_z), new Vector3(0, 0, 0), new Vector3(0, (float)Math.Cos(ugol - (float)Math.PI/2), 0)); //добавил это
...
            switch (e.KeyCode)
            {
                case Keys.W:
          	  //camera.arcRotate(0, 1);
          	  ugol -= 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
        	case Keys.S:
          	  //camera.arcRotate(0, -1);
          	  ugol += 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
        	case Keys.D:
          	  //camera.arcRotate(1, 0);
          	  ugol2 += 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
        	case Keys.A:
          	  //camera.arcRotate(-1, 0);
          	  ugol2 -= 0.02f;
          	  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
          	  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
          	  cam_y = (float)(r * Math.Cos(ugol));
          	  break;
                

            }
...

Это не то вращение камеры, которое в 3ds max (и его бесплатном варианте, gmax ). Это упрощённый вариант, когда камера всегда смотрит точно в центр вращения (за-hardcode-енный в {0, 0, 0}), так что он всегда проецируется точно в центр viewport-а. Но если в качестве центра вращения брать центр выделенного объекта, то не совсем понятно, как при таком подходе переключаться на другой объект. Резко менять ориентацию камеры? (раньше смотрела точно в центр старого объекта, теперь смотрит точно в центр нового объекта) Пользователю будет неприятно. Впрочем, если Kokon-у такой упрощённый вариант подходит (может, у него всегда будет ровно один объект), то хорошо, просто раньше он писал :
Kokonа вообще я хочу сделать чтобы камера облетала сцену как это сделано в 3d max или в любом другом 3d редакторе.
Ну и один и тот же код 4 раза -- неправильно, надо избегать дублирования кода:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
switch (e.KeyCode) {
case Keys.W:
  ugol -= 0.02f;
  calc_cam_pos();
  break;
case Keys.S:
  ugol += 0.02f;
  calc_cam_pos();
  break;
case Keys.D:
  ugol2 += 0.02f;
  calc_cam_pos();
  break;
case Keys.A:
  ugol2 -= 0.02f;
  calc_cam_pos();
  break;
}
...
void calc_cam_pos() {
  cam_z = (float)(-r * Math.Sin(ugol) * Math.Cos(ugol2));
  cam_x = (float)(r * Math.Sin(ugol) * Math.Sin(ugol2));
  cam_y = (float)(r * Math.Cos(ugol));
}

(код не компилировал)
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38172406
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот сделал почти точно по вашему коду. Поменял только double на float.
Код: c#
1.
Vector3 _cam_pos = new Vector3( 0, -200, 200 ); на Vector3 _cam_pos = new Vector3( 0, -1.97f, -90.0f );


ну я думаю это не принципиально.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace Camera
{
    class Camera
    {
        public enum CameraType
        {
            LANDOBJECT,
            AIRCRAFT
        };

        public CameraType cameraType;
        Vector3 _cam_pos = new Vector3( 0, -1.97f, -90.0f );

        // углы, задающие ориентацию камеры
        float _cam_yaw = 90;
        float _cam_pitch = -45;

        // оси камеры в мировых координатах
        Vector3 _cam_dir = new Vector3(0.0f, 0.0f, 1.0f);
        Vector3 _cam_right= new Vector3(1.0f, 0, 0);
        Vector3 _cam_up= new Vector3(0, 1.0f, 0.0f);

        Vector3 _arc_rotate_center =new Vector3( 0, 0, 0 ); // в мировых координатах



        public Camera()
        {
            cameraType = CameraType.AIRCRAFT;
        }
        public Camera(CameraType _cameraType)
        {
            cameraType = _cameraType;

        }
        public Matrix GetViewMatrix(Matrix v)
        {
            _cam_dir.Normalize();
            _cam_up = Vector3.Cross(_cam_dir, _cam_right);
            _cam_up.Normalize();
            _cam_right = Vector3.Cross(_cam_up, _cam_dir);
            _cam_right.Normalize();

       
            v.M11 = _cam_right.X;
            v.M12 = _cam_up.X;
            v.M13 = _cam_dir.X;
            v.M14 = 0.0f;

            v.M21 = _cam_right.Y;
            v.M22 = _cam_up.Y;
            v.M23 = _cam_dir.Y  ;
            v.M24 = 0.0f;

            v.M31 = _cam_right.Z;
            v.M32 = _cam_up.Z;
            v.M33 = _cam_dir.Z;
            v.M34 = 0.0f;

            v.M41 = -Vector3.Dot(_cam_right, _cam_pos);
            v.M42 = -Vector3.Dot(_cam_up, _cam_pos);
            v.M43 = -Vector3.Dot(_cam_dir, _cam_pos);//расстояние по оси Z
            v.M44 = 1.0f;
            return v;

        }

        private void calc_cam_axes()
        {
            _cam_dir.X = (float)Math.Cos(radFromDeg(_cam_pitch)) * (float)Math.Cos(radFromDeg(_cam_yaw));
            _cam_dir.Y = (float)Math.Cos(radFromDeg(_cam_pitch)) * (float)Math.Sin(radFromDeg(_cam_yaw));
            _cam_dir.Z = (float)Math.Sin(radFromDeg(_cam_pitch));

            _cam_right.X = (float)Math.Cos(radFromDeg(_cam_yaw - 90));
            _cam_right.Y = (float)Math.Sin(radFromDeg(_cam_yaw - 90));
            _cam_right.Z = 0;

            _cam_up = Vector3.Cross(_cam_right, _cam_dir);
        }
       
        private Vector3 rotate(Vector3 point_on_axis, Vector3 dir, float angle, Vector3 point)
        {
            Vector3 r = point - point_on_axis;
            dir.Normalize();
            float a = angle * (float)(Math.PI / 180.0f);
            return point_on_axis + (float)Math.Cos(a) * r + ((1 - (float)Math.Cos(a)) * Vector3.Dot(dir, r)) * dir + (float)Math.Sin(a) * Vector3.Cross(dir, r);           
        }
        
        private float radFromDeg(float angle)
        {
            return angle * (float)(Math.PI / 180);
        }
        public void arcRotate(int move_x, int move_y)
        {
            if (move_x != 0)
            {
                float yaw_diff = move_x;
                _cam_pos = rotate(_arc_rotate_center, new Vector3(0, 0, 1), yaw_diff, _cam_pos);
                _cam_yaw += yaw_diff;
                calc_cam_axes();
                
            }
            if (move_y != 0)
            {
                float pitch_diff = -move_y;
                _cam_pos = rotate(_arc_rotate_center,_cam_right, pitch_diff, _cam_pos);
                _cam_pitch += pitch_diff;
                calc_cam_axes();
            }
        }
       
    }
}



но когда я нажимаю на какую-нибудь кнопку, куб исчезает, видимо камера вообще улетает куда-то или смотрит в другую сторону. В приложении и проект есть и само приложение.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38172613
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:

KokonПоменял только double на float.Это да, не принципиально.

Kokon
Код: c#
1.
Vector3 _cam_pos = new Vector3( 0, -200, 200 ); на Vector3 _cam_pos = new Vector3( 0, -1.97f, -90.0f );

У меня вначале камера смотрит вниз (начальный _cam_pitch = -45 °), поэтому желательно, чтобы вначале камера была «над землёй» (начальный _cam_pos.z > 0), иначе вы не увидите объект, расположенный в {0, 0, 0}. Ну и начальный _cam_pos.y желательно подобрать так, чтобы камера не попала внутрь объекта.

Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
        public Matrix GetViewMatrix(Matrix v)
        {
            _cam_dir.Normalize();
            _cam_up = Vector3.Cross(_cam_dir, _cam_right);
            _cam_up.Normalize();
            _cam_right = Vector3.Cross(_cam_up, _cam_dir);
            _cam_right.Normalize();

       
            v.M11 = _cam_right.X;
            v.M12 = _cam_up.X;
            v.M13 = _cam_dir.X;
            v.M14 = 0.0f;

            v.M21 = _cam_right.Y;
            v.M22 = _cam_up.Y;
            v.M23 = _cam_dir.Y  ;
            v.M24 = 0.0f;

            v.M31 = _cam_right.Z;
            v.M32 = _cam_up.Z;
            v.M33 = _cam_dir.Z;
            v.M34 = 0.0f;

            v.M41 = -Vector3.Dot(_cam_right, _cam_pos);
            v.M42 = -Vector3.Dot(_cam_up, _cam_pos);
            v.M43 = -Vector3.Dot(_cam_dir, _cam_pos);//расстояние по оси Z
            v.M44 = 1.0f;
            return v;

        }

Выделенные строки -- лишние, их нет в моём коде . Оси камеры в мировых координатах (векторы _cam_dir, _cam_right, _cam_up) полностью рассчитываются в функции calc_cam_axes, дополнительные действия не нужны (например, не надо их нормализовывать, они и так единичные).

Kokon
Код: c#
1.
2.
3.
4.
        // оси камеры в мировых координатах
        Vector3 _cam_dir = new Vector3(0.0f, 0.0f, 1.0f);
        Vector3 _cam_right= new Vector3(1.0f, 0, 0);
        Vector3 _cam_up= new Vector3(0, 1.0f, 0.0f);

Лучше убрать эту инициализацию, и вместо неё добавить вызов функции calc_cam_axes в конструкторы класса Camera:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
public Camera() {
  cameraType = CameraType.AIRCRAFT;
  calc_cam_axes();
}

public Camera(CameraType cameraType_) {
  cameraType = cameraType_;
  calc_cam_axes();
}

(код не компилировал)
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38173267
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, вращается хорошо, спасибо. Только перспектива как-то сильно стала заметна. У куба передняя поверхность заметно меньше, чем задняя. Хотя это наверно у меня в коде косяк какой-то.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38174069
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:
KokonТолько перспектива как-то сильно стала заметна.Чтобы ослабить «перспективность», попробуйте отодвинуть камеру подальше от объекта. Ещё можно уменьшить угол обзора, указываемый при вызове Matrix.PerspectiveFovLH. Кстати, по поводу этого вызова:
ваш код
Код: c#
1.
Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1.0f, 100.0f);

Целочисленное деление здесь не подходит. Поэтому, скорее всего, надо добавить приведение к типу float.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38174991
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, подключил класс камеры к другому проекту. Там нарисована координатная сетка и оси координат. Вращается она как-то странно. Когда на W или S нажимаешь, то все нормально, а когда на A или D, то она вращается не вокруг оси Y, а вокруг оси Z. Не понятно то ли вращение неправильное, то ли камера не правильно установлена. Сетка вроде правильно рисуется, просто по координатам точек. Что интересно, в проекте с кубом все хорошо. Он вращается как надо. А здесь косяк. Приведу код. Вот код формы где все рисуется

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
138.
139.
140.
141.
142.
143.
144.
145.
146.
147.
148.
149.
150.
151.
152.
153.
154.
155.
156.
157.
158.
159.
160.
161.
162.
163.
164.
165.
166.
167.
168.
169.
170.
171.
172.
173.
174.
175.
176.
177.
178.
179.
180.
181.
182.
183.
184.
185.
186.
187.
188.
189.
190.
191.
192.
193.
194.
195.
196.
197.
198.
199.
200.
201.
202.
203.
204.
205.
206.
207.
208.
209.
210.
211.
212.
213.
214.
215.
216.
217.
218.
219.
220.
221.
222.
223.
224.
225.
226.
227.
228.
229.
230.
231.
232.
233.
234.
235.
236.
237.
238.
239.
240.
241.
242.
243.
244.
245.
246.
247.
248.
249.
250.
251.
252.
253.
254.
255.
256.
257.
258.
259.
260.
261.
262.
263.
 using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;
using System.Collections;
using System.Threading;



namespace WindowsFormsApplication1
{
    
    public partial class Form1 : Form
    {
        private Device device;
        private float angle;      
        private Panel viewportScreen1;       
               
        CustomVertex.TransformedColored[] vertsColumn;
        CustomVertex.TransformedColored[] vertsColumnPlus;
        CustomVertex.TransformedColored[] vertsColumnMinus;

        CustomVertex.TransformedColored[] vertsStrings;
        CustomVertex.TransformedColored[] vertsStringsPlus;
        CustomVertex.TransformedColored[] vertsStringsMinus;

       private int ColumnsCount = 21;//Количество колонок и строк в координатной сетке
        Color colorOfCoordMesh = Color.Gray;
        private Matrix v;
        
        private Thread g_mainThread;
        public bool g_running;
        private Camera camera=new Camera();

        private VertexBuffer vb = null;

        
        public Form1()
        {
         //   this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);
            InitializeComponent();
            
        }

      
        private void Form1_Load(object sender, EventArgs e)
        {

        }

        public void InitializeGraphics()
        {
            viewportScreen1 = panel1;
           // viewportScreen2 = panel12;

            PresentParameters pp= new PresentParameters();
            pp.Windowed = true;
            pp.SwapEffect = SwapEffect.Discard;
            pp.EnableAutoDepthStencil = true;
            pp.AutoDepthStencilFormat = DepthFormat.D16;
            pp.DeviceWindow = this.panel1;
            device = new Device(0, DeviceType.Hardware, this.panel1.Handle, CreateFlags.SoftwareVertexProcessing, pp);
            device.DeviceReset += new EventHandler(device_DeviceReset);
           device.RenderState.Ambient = Color.Blue;
          

           vb = new VertexBuffer(typeof(CustomVertex.PositionColored),
                              6,
                              device,
                              Usage.Dynamic | Usage.WriteOnly,
                              CustomVertex.PositionColored.Format,
                              Pool.Default);
           vb.Created += new EventHandler(vb_Created);
           vb_Created(vb, null); 
           g_running = true;
           g_mainThread = new Thread(new ThreadStart(MainLoop));
           g_mainThread.Name = "Main loop thread";
           g_mainThread.Start();
           FillArrayOfCoordMesh();
         
            
            

        }
        void vb_Created(object sender, EventArgs e)
        {
            VertexBuffer buffer = (VertexBuffer)sender;
            CustomVertex.PositionColored[] verts = new
                CustomVertex.PositionColored[6];
            // Задняя грань: треугольник 2-0-1 (невидимая сторона - обход левый)
            verts[0] = new CustomVertex.PositionColored(0.0F, 0.0F, 0.0F, Color.Red.ToArgb());
            verts[1] = new CustomVertex.PositionColored(0.0F, -10.0F, 0.0F, Color.Red.ToArgb());
            verts[2] = new CustomVertex.PositionColored(0.0F, 0.0F, 0.0F, Color.Blue.ToArgb());
            verts[3] = new CustomVertex.PositionColored(10.0F, 0.0F, 0.0F, Color.Blue.ToArgb());
            verts[4] = new CustomVertex.PositionColored(0.0F, 0.0F, 0.0F, Color.DeepPink.ToArgb());
            verts[5] = new CustomVertex.PositionColored(0.0F, 0.0F, 10.0F, Color.DeepPink.ToArgb());


            // Заполнить вершинный буфер данными треугольников
            buffer.SetData(verts, 0, LockFlags.None);
        }

        void device_DeviceReset(object sender, EventArgs e)
        {
            
        }

        private void MainLoop()
        {
            while (g_running)
            {
                
                RenderScene();
            }
        }

        

       
        private void SetupCamera()
        {
            device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, (float)viewportScreen1.Width / (float)viewportScreen1.Height, 1.0f, 100.0f);
            v = camera.GetViewMatrix(v);
            device.SetTransform(TransformType.View, v);          
            device.RenderState.Lighting = false;           
            device.RenderState.PointSize = 5.0f;
            angle += 0.1f;
            device.Lights[0].Type = LightType.Directional;
            device.Lights[0].Diffuse = Color.Red;
            device.Lights[0].Direction = new Vector3(0, -1, 0);
            device.Lights[0].Enabled = true;
            
        }


       protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
        {
       }

      



     

       private void FillArrayOfCoordMesh()
       {
           float step = 1;
           float firstCoord = (step * (ColumnsCount/2))*-1;
           
           
           float marginCoord = 10;//Крайняя координата колонки
            vertsColumnPlus = new CustomVertex.TransformedColored[ColumnsCount];
            vertsColumnMinus = new CustomVertex.TransformedColored[ColumnsCount];

            vertsStringsPlus = new CustomVertex.TransformedColored[ColumnsCount];
            vertsStringsMinus = new CustomVertex.TransformedColored[ColumnsCount];
         
           for (int i = 0; i < ColumnsCount; i++)
           {   //Колонки
               vertsColumnPlus[i].Position = new Vector4(firstCoord, 0, marginCoord, 1.0F);
               vertsColumnPlus[i].Color = colorOfCoordMesh.ToArgb();

               vertsColumnMinus[i].Position = new Vector4(firstCoord, 0, marginCoord * -1, 1.0F);
               vertsColumnMinus[i].Color = colorOfCoordMesh.ToArgb();
              //Строки
               vertsStringsPlus[i].Position = new Vector4(marginCoord, 0, firstCoord, 1.0F);
               vertsStringsPlus[i].Color = colorOfCoordMesh.ToArgb();

               vertsStringsMinus[i].Position = new Vector4(marginCoord * -1, 0, firstCoord, 1.0F);
               vertsStringsMinus[i].Color = colorOfCoordMesh.ToArgb();



               firstCoord += step;
           }


       }
       private void DrawCoordMesh()
       {

           device.RenderState.PointSize = 5.0f;
           device.VertexFormat = CustomVertex.PositionColored.Format;

           Material boxM = new Material();
           boxM.Ambient = colorOfCoordMesh;
           boxM.Diffuse = Color.White;
           device.Material = boxM;

                     
           for (int i = 0; i < ColumnsCount; i++)
           {
               vertsColumn = new CustomVertex.TransformedColored[2];
               vertsColumn[0].Position=vertsColumnPlus[i].Position;
               vertsColumn[0].Color = vertsColumnPlus[i].Color;

               vertsColumn[1].Position = vertsColumnMinus[i].Position;
               vertsColumn[1].Color = vertsColumnMinus[i].Color;

               device.Transform.World = Matrix.Translation(0, 0, 1.0f);
               device.DrawUserPrimitives(PrimitiveType.LineList, 1, vertsColumn);

               vertsStrings = new CustomVertex.TransformedColored[2];
               vertsStrings[0].Position = vertsStringsPlus[i].Position;
               vertsStrings[0].Color = vertsStringsPlus[i].Color;

               vertsStrings[1].Position = vertsStringsMinus[i].Position;
               vertsStrings[1].Color = vertsStringsMinus[i].Color;

               device.Transform.World = Matrix.Translation(0, 0, 1.0f);
               device.DrawUserPrimitives(PrimitiveType.LineList, 1, vertsStrings);
               
           }
           device.VertexFormat = CustomVertex.PositionColored.Format;
           device.SetStreamSource(0, vb, 0);
           device.DrawPrimitives(PrimitiveType.LineList, 0, 3);           
       }

      
       private void RenderScene()
       {
           device.Clear(ClearFlags.Target | ClearFlags.ZBuffer, Color.Aquamarine, 1.0f, 0);
           SetupCamera();
           device.BeginScene();
           DrawCoordMesh();
                 
           device.EndScene();
           device.Present();      

       }    

       private void Form1_FormClosing(object sender, FormClosingEventArgs e)
       {
           g_running = false;
       }
     
           private void Form1_KeyDown(object sender, KeyEventArgs e)
           {
               switch (e.KeyCode)
               {
                   case Keys.W:
                       camera.arcRotate(0, 5);
                       break;
                   case Keys.S:
                       camera.arcRotate(0, -5);
                       break;
                   case Keys.D:
                       camera.arcRotate(5, 0);
                       break;
                   case Keys.A:
                       camera.arcRotate(-5, 0);
                       break;               
               }                             
           }       
    }   
}




а вот код камеры


Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace WindowsFormsApplication1
{
    class Camera
    {
        public enum CameraType
        {
            LANDOBJECT,
            AIRCRAFT
        };

        public CameraType cameraType;
        public Vector3 _cam_pos = new Vector3(5.0f, -5.97f, -32.0f);
        // public Vector3 _cam_pos = new Vector3(10, -1, -43.0f);
        // углы, задающие ориентацию камеры
        public float _cam_yaw = 90;
        public float _cam_pitch = 80;
        //public float _cam_pitch = -45;

        // оси камеры в мировых координатах
        Vector3 _cam_dir;
        Vector3 _cam_right;
        Vector3 _cam_up;

        Vector3 _arc_rotate_center = new Vector3(0, 0, 0); // в мировых координатах



        public Camera()
        {
            cameraType = CameraType.AIRCRAFT;
            calc_cam_axes();
        }
        public Camera(CameraType _cameraType)
        {
            cameraType = _cameraType;

        }
        public Matrix GetViewMatrix(Matrix v)
        {

            v.M11 = _cam_right.X;
            v.M12 = _cam_up.X;
            v.M13 = _cam_dir.X;
            v.M14 = 0.0f;

            v.M21 = _cam_right.Y;
            v.M22 = _cam_up.Y;
            v.M23 = _cam_dir.Y;
            v.M24 = 0.0f;

            v.M31 = _cam_right.Z;
            v.M32 = _cam_up.Z;
            v.M33 = _cam_dir.Z;
            v.M34 = 0.0f;

            v.M41 = -Vector3.Dot(_cam_right, _cam_pos);
            v.M42 = -Vector3.Dot(_cam_up, _cam_pos);
            v.M43 = -Vector3.Dot(_cam_dir, _cam_pos);//расстояние по оси Z
            v.M44 = 1.0f;
            return v;

        }

        private void calc_cam_axes()
        {
            _cam_dir.X = (float)Math.Cos(radFromDeg(_cam_pitch)) * (float)Math.Cos(radFromDeg(_cam_yaw));
            _cam_dir.Y = (float)Math.Cos(radFromDeg(_cam_pitch)) * (float)Math.Sin(radFromDeg(_cam_yaw));
            _cam_dir.Z = (float)Math.Sin(radFromDeg(_cam_pitch));

            _cam_right.X = (float)Math.Cos(radFromDeg(_cam_yaw - 90));
            _cam_right.Y = (float)Math.Sin(radFromDeg(_cam_yaw - 90));
            _cam_right.Z = 0;

            _cam_up = Vector3.Cross(_cam_right, _cam_dir);
        }

        private Vector3 rotate(Vector3 point_on_axis, Vector3 dir, float angle, Vector3 point)
        {
            Vector3 r = point - point_on_axis;
            dir.Normalize();
            float a = angle * (float)(Math.PI / 180.0f);
            return point_on_axis + (float)Math.Cos(a) * r + ((1 - (float)Math.Cos(a)) * Vector3.Dot(dir, r)) * dir + (float)Math.Sin(a) * Vector3.Cross(dir, r);
        }

        private float radFromDeg(float angle)
        {
            return angle * (float)(Math.PI / 180);
        }
        public void arcRotate(int move_x, int move_y)
        {
            if (move_x != 0)
            {
                float yaw_diff = move_x;
                _cam_pos = rotate(_arc_rotate_center, new Vector3(0, 0, 1), yaw_diff, _cam_pos);
                _cam_yaw += yaw_diff;
                calc_cam_axes();

            }
            if (move_y != 0)
            {
                float pitch_diff = -move_y;
                _cam_pos = rotate(_arc_rotate_center, _cam_right, pitch_diff, _cam_pos);
                _cam_pitch += pitch_diff;
                calc_cam_axes();
            }
        }
    

    }
}


...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38175373
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:

KokonТам нарисована координатная сетка и оси координат. Вращается она как-то странно. Когда на W или S нажимаешь, то все нормально, а когда на A или D, то она вращается не вокруг оси Y, а вокруг оси Z.Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
           for (int i = 0; i < ColumnsCount; i++)
           {   //Колонки
               vertsColumnPlus[i].Position = new Vector4(firstCoord, 0, marginCoord, 1.0F);
               ...
               vertsColumnMinus[i].Position = new Vector4(firstCoord, 0, marginCoord * -1, 1.0F);
               ...
              //Строки
               vertsStringsPlus[i].Position = new Vector4(marginCoord, 0, firstCoord, 1.0F);
               ...
               vertsStringsMinus[i].Position = new Vector4(marginCoord * -1, 0, firstCoord, 1.0F);
               ...
               firstCoord += step;
           }

У вас, похоже, сетка лежит в плоскости «y = 0». А я писал код, подразумевая традиционную мировую систему координат, в которой «поверхность земли» -- это плоскость «z = 0», а также:
* ось x идёт «по земле» на восток
* ось y идёт «по земле» на север
* ось z идёт вертикально вверх, «в небо»
Кстати, именно такая мировая система координат используется в 3ds max (и gmax), и я вам советую перейти на неё.

KokonЧто интересно, в проекте с кубом все хорошо. Он вращается как надо.Куб одинаковый по всем осям, поэтому расхождение в системе координат незаметно.

Kokon
Код: c#
1.
Matrix.PerspectiveFovLH((float)Math.PI / 4, (float)viewportScreen1.Width / (float)viewportScreen1.Height, 1.0f, 100.0f)

Да, с float-овым делением должно быть правильно.

Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
        private Thread g_mainThread;
        public bool g_running;
...
        public void InitializeGraphics()
        {
           ...
           g_running = true;
           g_mainThread = new Thread(new ThreadStart(MainLoop));
           g_mainThread.Name = "Main loop thread";
           g_mainThread.Start();
           ...
        }
...
        private void MainLoop()
        {
            while (g_running)
            {
                
                RenderScene();
            }
        }
...
       private void Form1_FormClosing(object sender, FormClosingEventArgs e)
       {
           g_running = false;
       }

Осторожно, много-поточность -- не для начинающих.

Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
        CustomVertex.TransformedColored[] vertsColumn;
        CustomVertex.TransformedColored[] vertsColumnPlus;
        CustomVertex.TransformedColored[] vertsColumnMinus;

        CustomVertex.TransformedColored[] vertsStrings;
        CustomVertex.TransformedColored[] vertsStringsPlus;
        CustomVertex.TransformedColored[] vertsStringsMinus;

В данном случае лучше перевести «строки» как «rows», а не «strings».

Kokon
Код: c#
1.
marginCoord * -1

Зачем умножать на -1, есть же унарный минус: -marginCoord.

Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
        public Camera()
        {
            cameraType = CameraType.AIRCRAFT;
            calc_cam_axes();
        }
        public Camera(CameraType _cameraType)
        {
            cameraType = _cameraType;

        }

Лучше вставить вызов метода calc_cam_axes и во второй конструктор тоже, он ничем не хуже первого :).
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38176306
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, поменял оси теперь сетка хорошо вращается. Теперь возникла другая проблема))))) Я в своем проекте сделал чтобы по клику мыши рисовался или куб или цилиндр. Когда была просто статичная камера(через LookAt сделанная), то рисовалось все правильно, а вот когда динамику добавил примитивы уже рисуются где попало. Допустим когда в центр сетки кликаешь, координаты не 0,0,0 выдаются, а вообще левые цифры. И при этом кликнул в центре сетки одни координаты, не сдвигая курсора покрутил камеру, снова кликнул уже другие. Т.е. получается будто бы координаты клика зависят от положения камеры. Я прикрепил файл там как раз можно это увидеть.
а координаты я в этом коде определяю
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
            Matrix proj = device.Transform.Projection;
           Matrix view = device.Transform.View;
           Matrix mWorld = Matrix.Identity;
           Vector3 near = new Vector3(e.X, e.Y, 0); // или так  Vector3 near =camera._pos_cam;
           Vector3 far = new Vector3(e.X, e.Y, 1);
           Vector3 dir;
           float dist = 18.0f;//расстояние камеры по оси Z
           near.Unproject(device.Viewport, proj, view, Matrix.Identity);
           far.Unproject(device.Viewport, proj, view, Matrix.Identity);
           dir = Vector3.Normalize(far - near);           
           Vector3 new_obj_pos = near + dist * dir;
           this.Text = " x " + new_obj_pos.X.ToString() + " y " + new_obj_pos.Y.ToString() + " z " + new_obj_pos.Z.ToString();



при этом если курсор на центр сетки поставить и вращать ее вертикально то заметно что центр сильно смещается относительно курсора, а если в стороны то смещения не происходит.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38176833
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:

KokonДопустим когда в центр сетки кликаешь, координаты не 0,0,0 выдаются, а вообще левые цифры.Попробуйте размещать новые объекты так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
// пользователь щёлкнул мышью в какой-то пиксел
// этому пикселу соответствует луч, выходящий из камеры (то есть начало луча -- точка _cam_pos)
// берём любую точку на этом луче
Vector3 ray_point = Vector3.Unproject(new Vector3(e.X, e.Y, 1), device.Viewport, device.Transform.Projection, device.Transform.View, Matrix.Identity);
// вместо 1 можно взять любое число от 0 до 1
// ray_point -- в мировых координатах

// вычисляем направление луча
Vector3 ray_dir = ray_point - _cam_pos;
// ray_dir можно нормализовать, но в данном случае это необязательно

// параметрическое задание луча (в векторной форме):
// ray_point = _cam_pos + t * ray_dir,  где t -- параметр, любое число >= 0
//
// параметрическое задание луча (в скалярной форме):
// ray_point.x = _cam_pos.x + t * ray_dir.x
// ray_point.y = _cam_pos.y + t * ray_dir.y
// ray_point.z = _cam_pos.z + t * ray_dir.z
//
// ищем пересечение луча с плоскостью «z = 0», чтобы создать в этом месте новый объект
// ray_point.z = 0  <=>  _cam_pos.z + t * ray_dir.z = 0  =>  t = -_cam_pos.z / ray_dir.z
if (ray_dir.z != 0) /* продолжаем */; else /* не судьба */ return;
float t = -_cam_pos.z / ray_dir.z;
if (t >= 0) /* продолжаем */; else /* не судьба */ return;

// new_obj_pos = _cam_pos + t * ray_dir
Vector3 new_obj_pos = new Vector3(_cam_pos.x + t * ray_dir.x, _cam_pos.y + t * ray_dir.y, 0);
// new_obj_pos -- в мировых координатах

// создаём новый объект в точке new_obj_pos
...

(код не компилировал)
Если не поможет, покажите код, как создаёте/рисуете объекты.

Kokonпри этом если курсор на центр сетки поставить и вращать ее вертикально то заметно что центр сильно смещается относительно курсора, а если в стороны то смещения не происходит.Насколько я понял, вы зачем-то рисуете сетку со смещением вверх на 1:
Kokon
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
       private void DrawCoordMesh()
       {
           ...
           for (int i = 0; i < ColumnsCount; i++)
           {
               ...
               device.Transform.World = Matrix.Translation(0, 0, 1.0f);
               device.DrawUserPrimitives(PrimitiveType.LineList, 1, vertsColumn);

               ...
               device.Transform.World = Matrix.Translation(0, 0, 1.0f);
               device.DrawUserPrimitives(PrimitiveType.LineList, 1, vertsStrings);
               
           }
           ...
       }

Таким образом, сетка лежит в плоскости «z = 1». Рисуйте сетку без смещения, чтобы она лежала в плоскости «z = 0»:
Код: c#
1.
2.
3.
// рисуем сетку
device.Transform.World = Matrix.Identity;
...

(код не компилировал)
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38177039
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, все классно работает и рисование объекта и его выделение и повороты. Спасибо! У меня сетка была сдвинута по оси Z потому что когда я примитив рисовал сетка тоже устанавливалась в в его положение, т.е. постоянно сдвигалась. А про то чтобы сделать при рисовании сетки единичную матрицу я тогда и не догадался. Теперь все хорошо. Кстати на счет многопоточности. Я ее использовал для того чтобы можно было рисовать на панели, а не только на форме. Просто когда на форме рисовал использовал событие onPaint, а для панели им воспользоваться не получилось, уже точно не помню почему, но не работало так как надо. Вот и пришлось использовать потоки. Хотя и с ними проблем хватает, например не могу обратиться к элементам на форме, потому что они созданы в другом потоке. Ну это я на потом оставил, хотел сначала с камерой и созданием примитивов разобраться.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38178353
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:

KokonКстати на счет многопоточности. Я ее использовал для того чтобы можно было рисовать на панели, а не только на форме.Всё-таки должен быть какой-то способ рисовать на панели без использования много-поточности (которая здесь не обоснована и может создать серьёзные проблемы). Ну как-то типа:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
private Panel viewport;
...
// вызывается в главном потоке, когда очередь сообщений пуста
void idle() {
  if (playing_animation()) { // анимация -- это например вращение куба/цилиндра
    viewport.Invalidate(); // запрашиваем перерисовку
  }
}

(код не компилировал)

Kokonхотел сначала с камерой и созданием примитивов разобраться.Кстати, по поводу вращения камеры. В разных 3D-редакторах это по-разному сделано. В Blender -е например другой способ, можете глянуть. Но мне max-овский способ привычнее.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38179120
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов,
пытаюсь привязать вращение камеры к движению мыши. вроде сначала казалось, что легко, а на деле оказывается, что не совсем легко.
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
private void panel1_MouseDown(object sender, MouseEventArgs e)
           {
             getMousePosition(e,true);// при MouseDown возвращает позицию клика(mouse_last_point), при MouseMove текущюю позицию курсора(mouse_pos) 
             // эти точки в экранных координатах, просто для того чтобы знать в каком направлении двигается мышь относительно точки клика
             last_screen_mouseX = e.X; 
             last_screen_mouseY = e.Y;
           }

private void panel1_MouseMove(object sender, MouseEventArgs e)
           {
                getMousePosition(e,false);       
                 float moveX = 0;
                 float moveY = 0;    
                
               Vector3 mouseDelta = mouse_pos - mouse_last_point;//пока не используется
               Vector3 rotationDelta = mouseDelta * rotation_gain;//пока не используется            
              
                   if (e.Button == MouseButtons.Left)
                   {
                        if (e.X > last_screen_mouseX) { moveX = 5.0f ; } 
                       if (e.X < last_screen_mouseX) { moveX = -5.0f ; } 

                        if (e.Y > last_screen_mouseY) { moveY = 5.0f ; } ;
                       if (e.Y < last_screen_mouseY) { moveY = -5.0f ; } 
                       camera.arcRotate(moveX, moveY);           
                   }            
           }


получается, что moveX и moveY не всегда обнуляются, т.е. когда точно двигаю мышью по Х(в экранных координатах) Y не меняется, то вращается все правильно, а когда двину по Y, то moveY потом не обнуляется и камера вращается как попало в обоих плоскостях. Хотя при наступлении этого события эти переменных должны обнуляться.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38179291
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:
Зачем так сложно? Попробуйте проще:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
int last_screen_mouseX, last_screen_mouseY;
...
private void panel1_MouseDown(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Middle) {
    last_screen_mouseX = e.X;
    last_screen_mouseY = e.Y;
  }
}

private void panel1_MouseMove(object sender, MouseEventArgs e) {
  if (e.Button == MouseButtons.Middle) {
    // берём moveX/moveY из движений мыши
    camera.arcRotate(e.X - last_screen_mouseX, -(e.Y - last_screen_mouseY));
    last_screen_mouseX = e.X;
    last_screen_mouseY = e.Y;
  }
}

(код не компилировал)
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38179350
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов,как все просто оказалось))) Спасибо, работает как надо
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38180688
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:
Кстати, если вас смущает моя реализация функции rotate, то можете попробовать такую:
Код: c#
1.
2.
3.
4.
// поворачивает точку вокруг оси
static Vector3 rotate(Vector3 point_on_axis, Vector3 axis_dir, float angle, Vector3 point) {
  return point_on_axis + Vector3.TransformCoordinate(point - point_on_axis, Matrix.RotationAxis(axis_dir, rad_from_deg(-angle)));
}

(код не компилировал)
Вроде должно работать так же, только насчёт минуса перед углом не уверен.
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38181215
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, да меня то формула не смущает. Просто я ее не понимаю. Если не лень объясните пожалуйста. А в ее сами вывели или где-то она расписана?
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38181749
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, кстати не знаете, что можно почитать об архитектуре 3D приложений?
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38187044
Пётр Седов
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
2 Kokon:

KokonПётр Седов, да меня то формула не смущает. Просто я ее не понимаю. Если не лень объясните пожалуйста. А в ее сами вывели или где-то она расписана?Сейчас уже не помню точно, но скорее всего поворот точки вокруг произвольной оси я взял из книги «Advanced Animation and Rendering Techniques» (авторы: Alan Watt, Mark Watt):
(в первом абзаце возможно имеется в виду «of an amount θ about an axis n »)
15 Overview and low-level motion specification
...
15.3 Motion control
...
15.3.8 Parametrization of orientation
...
Angular displacement

We define orientation as an angular displacement given by ( θ , n ) of an amount about an axis n . Just as we did for Euler angle notation, we shall derive the rotational matrix in terms of this new notation, so instead of R ( θ 1 , θ 2 , θ 3 ) we write R ( θ , n ). Consider the angular displacement acting on a vector r taking it to position Rr as shown in Figure 15.20.

The problem can be decomposed by resolving r into components parallel to n , r , which by definition remains unchanged after rotation, and perpendicular to n , r in the plane passing through r and Rr .

r = ( n · r ) n
r = r - ( n · r ) n

r is rotated into position Rr . We construct a vector perpendicular to r and lying in the plane. In order to evaluate this rotation, we write:

V = n × r = n × r

So

Rr = (cos θ ) r + (sin θ ) V

hence

Rr = Rr + Rr
= Rr + (cos θ ) r + (sin θ ) V
= ( n · r ) n + cos θ ( r - ( n · r ) n ) + (sin θ ) n × r
= (cos θ ) r + (1 - cos θ ) n ( n · r ) + (sin θ ) n × r
Мой код :
Пётр Седов
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
// поворачивает точку вокруг оси
Vec_3 rotate(const Vec_3& point_on_axis, const Vec_3& axis_dir, double angle, const Vec_3& point) {
  assert(fabs(len(axis_dir) - 1) < 1e-3); // axis_dir должен быть единичным вектором
  Vec_3 r = point - point_on_axis;
  double a = rad_from_deg(angle);
  return point_on_axis + cos(a) * r + ((1 - cos(a)) * dot(axis_dir, r)) * axis_dir + sin(a) * cross(axis_dir, r);
}


Не знаю, как у вас с английским, в общем там ключевой момент в том, что вектор r (который надо повернуть) разбивается на 2 части:
r = r + r
r параллелен оси вращения, r перпендикулярен. Нам надо получить Rr , и поскольку вращение -- линейный оператор, то:
R ( r + r ) = Rr + Rr
С параллельной частью всё просто: Rr = r . С перпендикулярной частью чуть посложнее, похоже на полярные координаты: Rr = cos θ r + sin θ V .

Они там не пишут явно, но имеют в виду:

* Ось вращения проходит через начало координат (точка {0, 0, 0}). Обобщить на случай, когда не проходит, легко: сначала переходим в систему координат, где ось вращения проходит через начало координат, делаем поворот, затем возвращаемся в исходную систему координат.
Пётр Седов
Код: plaintext
1.
2.
3.
Vec_3 r = point - point_on_axis;
...
return point_on_axis + ...;


* Вектор n (направление оси вращения; в моём коде -- axis_dir) -- единичный.
Пётр Седов
Код: plaintext
1.
assert(fabs(len(axis_dir) - 1) < 1e-3); // axis_dir должен быть единичным вектором


KokonПётр Седов, кстати не знаете, что можно почитать об архитектуре 3D приложений?Не знаю. Но подозреваю, что архитектура 3D-редакторов более/менее такая же, как у обычных редакторов, отличается только рисование объектов и hit test (обнаружение, на какой объект щёлкнул пользователь).
...
Рейтинг: 0 / 0
DirectX вращение камеры вокруг центра
    #38190594
Kokon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пётр Седов, спасибо, поразбираюсь в формулах. Да и книгу надо будет эту скачать, может что-нибудь полезное для себя найду.
...
Рейтинг: 0 / 0
32 сообщений из 32, показаны все 2 страниц
Форумы / Программирование [игнор отключен] [закрыт для гостей] / DirectX вращение камеры вокруг центра
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]