Beispiel #1
0
    private void UpdateModelViewMatrix() // метод вызывается при измении свойств cameraAngle и cameraDistance
    {
        #region Обновление объектно-видовой матрицы ---------------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            DMatrix4 modelMat = DMatrix4.Identity;

            RotateMatrix(ref modelMat, Rotation.X, Rotation.Y, Rotation.Z);
            ScaleMatrix(ref modelMat, Scale.X, Scale.Y, Scale.Z);

            gl.MatrixMode(OpenGL.GL_MODELVIEW);
            gl.LoadMatrix(modelMat.ToArray(true));
        });
        #endregion
    }
Beispiel #2
0
 private void UpdateDisplayMode() // метод вызывается при измении свойств cameraAngle и cameraDistance
 {
     #region Обновление объектно-видовой матрицы ---------------------------------------------------------
     RenderDevice.AddScheduleTask((gl, s) =>
     {
         if (Wireframe)
         {
             gl.PolygonMode(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_LINE);
         }
         else
         {
             gl.PolygonMode(OpenGL.GL_FRONT_AND_BACK, OpenGL.GL_FILL);
         }
     });
     #endregion
 }
Beispiel #3
0
    private void UpdateModelViewMatrix() // метод вызывается при измении свойств cameraAngle и cameraDistance
    {
        #region Обновление объектно-видовой матрицы ---------------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) => {
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
            gl.LoadIdentity();

            gl.Translate(Shift.X, Shift.Y, 0.0);
            gl.Rotate(Rotation.X, 1.0, 0.0, 0.0);
            gl.Rotate(Rotation.Y, 0.0, 1.0, 0.0);
            gl.Rotate(Rotation.Z, 0.0, 0.0, 1.0);
            gl.Translate(Position.X, Position.Y, Position.Z);
            gl.Scale(Scale.X, Scale.Y, Scale.Z);
        });
        #endregion
    }
Beispiel #4
0
    private void UpdateModelViewMatrix() // метод вызывается при измении свойств cameraAngle и cameraDistance
    {
        #region Обновление объектно-видовой матрицы ---------------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            gl.MatrixMode(OpenGL.GL_MODELVIEW);
            var deg2rad = Math.PI / 180; // Вращается камера, а не сам объект
            double phi  = deg2rad * cameraAngle.X;
            double teta = deg2rad * cameraAngle.Y;
            double psi  = deg2rad * cameraAngle.Z;
            // матрицы поворота вокруг осей
            DMatrix3 RX = new DMatrix3(1, 0, 0,
                                       0, Math.Cos(phi), -Math.Sin(phi),
                                       0, Math.Sin(phi), Math.Cos(phi));

            DMatrix3 RY = new DMatrix3(Math.Cos(teta), 0, Math.Sin(teta),
                                       0, 1, 0,
                                       -Math.Sin(teta), 0, Math.Cos(teta));

            DMatrix3 RZ = new DMatrix3(Math.Cos(psi), -Math.Sin(psi), 0,
                                       Math.Sin(psi), Math.Cos(psi), 0,
                                       0, 0, 1);
            var cameraTransform   = (RX * RY) * RZ;
            var cameraPosition    = cameraTransform * new DVector3(0, 0, cameraDistance);
            var cameraUpDirection = cameraTransform * new DVector3(0, 1, 0);
            // Мировая матрица (преобразование локальной системы координат в мировую)
            mMatrix = DMatrix4.Identity; // нет никаких преобразований над объекта
            // Видовая матрица (переход из мировой системы координат к системе координат камеры)
            vMatrix = LookAt(DMatrix4.Identity, cameraPosition, DVector3.Zero, cameraUpDirection);
            // матрица ModelView
            var mvMatrix = vMatrix * mMatrix;
            gl.LoadMatrix(mvMatrix.ToArray(true));


            //gl.Rotate(45, 1f, 0f, 0);
            //gl.Rotate(-45, 0f, 1f, 0);
        });
        #endregion
    }
Beispiel #5
0
 private void UpdateModelViewMatrix() // метод вызывается при измении свойств cameraAngle и cameraDistance
 {
     #region Обновление объектно-видовой матрицы ---------------------------------------------------------
     RenderDevice.AddScheduleTask((gl, s) => { });
     #endregion
 }
Beispiel #6
0
    protected override void OnMainWindowLoad(object sender, EventArgs args)
    {
        base.VSPanelWidth = 260;
        base.ValueStorage.RightColWidth = 60;
        base.RenderDevice.VSync         = 1;

        #region Обработчики событий мыши и клавиатуры -------------------------------------------------------
        RenderDevice.MouseMoveWithLeftBtnDown += (s, e) => Rotation += new DVector3(e.MovDeltaY, e.MovDeltaX, 0);

        RenderDevice.MouseMoveWithRightBtnDown += (s, e) => {
            double W = base.RenderDevice.Width;
            double H = base.RenderDevice.Height;

            double AspectRatio = W / H;
        };

        #endregion

        InclinedCylinder();

        #region  Инициализация OGL и параметров рендера -----------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            gl.FrontFace(OpenGL.GL_CCW);
            gl.Enable(OpenGL.GL_CULL_FACE);
            gl.CullFace(OpenGL.GL_BACK);

            gl.ClearColor(0.2f, 0.6f, 1.0f, 1.0f);


            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.DepthFunc(OpenGL.GL_LEQUAL);
            gl.ClearDepth(1.0f);    // 0 - ближе, 1 - далеко
            gl.ClearStencil(0);
        });
        #endregion

        #region Инициализация буфера вершин -----------------------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            uint[] VertexVBOIDtempArray = new uint[1];
            gl.GenBuffers(1, VertexVBOIDtempArray);

            VertexVBOID = VertexVBOIDtempArray[0];

            uint[] IndexVBOIDtempArray = new uint[1];
            gl.GenBuffers(1, IndexVBOIDtempArray);

            IndexVBOID = IndexVBOIDtempArray[0];

            vertexShader = gl.CreateShader(OpenGL.GL_VERTEX_SHADER);
            gl.ShaderSource(vertexShader, ReadShader("VertexShader.vert"));
            gl.CompileShader(vertexShader);

            ShaderLog(gl, vertexShader);

            fragmentShader = gl.CreateShader(OpenGL.GL_FRAGMENT_SHADER);
            gl.ShaderSource(fragmentShader, ReadShader("FragmentShader.frag"));
            gl.CompileShader(fragmentShader);

            ShaderLog(gl, fragmentShader);

            shaderProgram = gl.CreateProgram();

            gl.AttachShader(shaderProgram, vertexShader);
            gl.AttachShader(shaderProgram, fragmentShader);

            gl.LinkProgram(shaderProgram);
            ProgramLog(gl, shaderProgram);
        }, this);
        #endregion

        #region Уничтожение буфера вершин по завершению работы OGL ------------------------------------------
        RenderDevice.Closed += (s, e) => // Событие выполняется в контексте потока OGL при завершении работы
        {
            var gl = e.gl;

            gl.DeleteBuffers(2, new uint[2] {
                VertexVBOID, IndexVBOID
            });

            gl.DeleteShader(vertexShader);
            gl.DeleteShader(fragmentShader);
            gl.DeleteProgram(shaderProgram);
        };
        #endregion

        #region Обновление матрицы проекции при изменении размеров окна и запуске приложения ----------------
        RenderDevice.Resized += (s, e) =>
        {
            var gl = e.gl;

            UpdateProjectionMatrix(gl);
        };
        #endregion
    }
Beispiel #7
0
    protected override void OnMainWindowLoad(object sender, EventArgs args)
    {
        base.ValueStorage.Font          = new Font("Courier New", 12f);
        base.ValueStorage.ForeColor     = Color.Black;
        base.ValueStorage.RowHeight     = 30;
        base.ValueStorage.BackColor     = Color.FromArgb(180, 180, 180);
        base.MainWindow.BackColor       = Color.FromArgb(160, 160, 160);
        base.ValueStorage.RightColWidth = 70;
        base.VSPanelWidth    = 480;
        base.VSPanelLeft     = true;
        base.MainWindow.Size = new Size(960, 640);

        #region Обработчики событий мыши и клавиатуры -------------------------------------------------------
        RenderDevice.MouseMoveWithLeftBtnDown += (s, e) => cameraAngle += new DVector3(-e.MovDeltaY, -e.MovDeltaX, 0);
        RenderDevice.MouseWheel += (s, e) => cameraDistance -= e.Delta / 10.0;
        #endregion


        // Как было отмеченно выше вся работа связанная с OGL должна выполнятся в одном потоке. Тут работа с OGL
        // осуществляется в отдельном потоке, а метод OnMainWindowLoad() является событием возбуждаемым потоком
        // пользовательского интерфейса (UI). Поэтой причине весь код ниже добавляется в диспетчер устройства
        // вывода (метод AddScheduleTask() объекта RenderDevice) и выполняется ассинхронно в контексте потока
        // OGL. Сам диспетчер является очередью типа FIFO (First In First Out - т.е. задания обрабатываются
        // строго в порядке их поступления) и гарантирует, что все задания добавленные в OnMainWindowLoad()
        // будут выполнены до первого вызова метода OnDeviceUpdate() (aka OnPaint)

        #region  Инициализация OGL и параметров рендера -----------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            //gl.Disable(OpenGL.GL_DEPTH_TEST);
            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.Enable(OpenGL.GL_CULL_FACE);
            gl.CullFace(OpenGL.GL_BACK); // отбросить полигоны, повёрнутые изнанкой
            gl.ClearColor(1, 1, 1, 0);
            gl.FrontFace(OpenGL.GL_CW);  // обход вершин по часовой стрелки
            //gl.PolygonMode(OpenGL.GL_FRONT, OpenGL.GL_FILL); // закрашиваются полигоны, повёрнутые лицевой стороной
            gl.PolygonMode(OpenGL.GL_FRONT, OpenGL.GL_LINE);
            gl.PolygonMode(OpenGL.GL_BACK, OpenGL.GL_FILL);
        });
        #endregion

        #region Загрузка и компиляция шейдера

        var errorhandler = new Action <string, object, object>((format, arg0, arg1) =>
        {
            string errormessage = String.Format(format, arg0, arg1);
            Trace.WriteLine(errormessage);
            throw new Exception(errormessage);
            MessageBox.Show(errormessage, "SHADER CREATION ERROR", MessageBoxButtons.OK, MessageBoxIcon.Error);
            Application.Exit();
        });



        RenderDevice.AddScheduleTask((gl, s) =>
        {
            var parameters     = new int[1];
            uint uit_ver       = gl.CreateShader(OpenGL.GL_VERTEX_SHADER);
            uint uit_frag      = gl.CreateShader(OpenGL.GL_FRAGMENT_SHADER);
            var compile_shader = new Action <uint>(shader =>
            {
                gl.CompileShader(shader);
                // Проверяем была ли компиляция выполнена успешно
                gl.GetShader(shader, OpenGL.GL_COMPILE_STATUS, parameters);
                if (parameters[0] != OpenGL.GL_TRUE)
                {
                    // В случае если компиляция не удалась пытаемся добиться от OGL
                    // что именно ему не понравилось. Для этого вначале получаем длину
                    // сообщения, выделим память под него, а затем уже запрашиваем
                    // скопировать туда само сообщение. В случае C# это выглядит
                    // немного иначе, но суть таже.
                    gl.GetShader(shader, OpenGL.GL_INFO_LOG_LENGTH, parameters);
                    StringBuilder strbuilder = new StringBuilder(parameters[0]);
                    gl.GetShaderInfoLog(shader, parameters[0], IntPtr.Zero, strbuilder);
                    errorhandler("OpenGL Error: ошибка во время компиляции {1}.\n{0}",
                                 strbuilder.ToString(), shader == uit_ver ? "VERTEX_SHADER"
                    : shader == uit_frag ? "FRAGMENT_SHADER" : "??????????_SHADER");
                }
            });

            var shader_vert = HelpUtils.GetTextFileFromRes("shader.vert");
            var shader_frag = HelpUtils.GetTextFileFromRes("shader.frag");
            //return;
            gl.ShaderSource(uit_ver, shader_vert);
            gl.ShaderSource(uit_frag, shader_frag);
            compile_shader(uit_ver);
            compile_shader(uit_frag);
            program = gl.CreateProgram();
            gl.AttachShader(program, uit_ver);
            gl.AttachShader(program, uit_frag);
            //gl.LinkProgram(program);

            gl.LinkProgram(program);
            gl.GetProgram(program, OpenGL.GL_LINK_STATUS, parameters);
            if (parameters[0] != OpenGL.GL_TRUE)
            {
                errorhandler("OpenGL Error: ошибка линковки програмы шейдера", null, null);
            }

            attrib_loc[0]  = (uint)gl.GetAttribLocation(program, "position");
            attrib_loc[1]  = (uint)gl.GetAttribLocation(program, "normal");
            uniform_loc[0] = (uint)gl.GetUniformLocation(program, "projection");
            uniform_loc[1] = (uint)gl.GetUniformLocation(program, "view");
            uniform_loc[2] = (uint)gl.GetUniformLocation(program, "model");
            gl.UseProgram(program);
        });
        #endregion

        #region Инициализация буфера вершин -----------------------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            gl.EnableClientState(OpenGL.GL_VERTEX_ARRAY);
            gl.EnableClientState(OpenGL.GL_NORMAL_ARRAY);
            gl.EnableClientState(OpenGL.GL_INDEX_ARRAY);
            gl.EnableClientState(OpenGL.GL_COLOR_ARRAY);

            gl.GenBuffers(buffers.Length, buffers);
        }, this);
        #endregion

        #region Уничтожение буфера вершин по завершению работы OGL ------------------------------------------
        RenderDevice.Closed += (s, e) => // Событие выполняется в контексте потока OGL при завершении работы
        {
            var gl = e.gl;
            gl.DisableClientState(OpenGL.GL_VERTEX_ARRAY);
            gl.DisableClientState(OpenGL.GL_NORMAL_ARRAY);
            gl.DisableClientState(OpenGL.GL_INDEX_ARRAY);
            gl.DisableClientState(OpenGL.GL_COLOR_ARRAY);
        };
        #endregion

        #region Обновление матрицы проекции при изменении размеров окна и запуске приложения ----------------
        RenderDevice.Resized += (s, e) =>
        {
            var gl = e.gl;
            gl.MatrixMode(OpenGL.GL_PROJECTION);
            pMatrix = Perspective(60, (double)e.Width / e.Height, 0.1, 100);

            gl.LoadMatrix(pMatrix.ToArray(true));
        };
        #endregion
    }
Beispiel #8
0
    protected override void OnMainWindowLoad(object sender, EventArgs args)
    {
        base.VSPanelWidth = 260;
        base.ValueStorage.RightColWidth = 60;
        base.RenderDevice.VSync         = 1;

        #region Обработчики событий мыши и клавиатуры -------------------------------------------------------
        RenderDevice.MouseMoveWithLeftBtnDown  += (s, e) => { };
        RenderDevice.MouseMoveWithRightBtnDown += (s, e) => { };
        RenderDevice.MouseLeftBtnDown          += (s, e) => {
            DVector2 norm = NormalizeCoords(e.Location.X, e.Location.Y);

            double X = (norm.X - ShiftX) * Scale;
            double Y = (norm.Y - ShiftY) * Scale;

            text = $"{X}  {Y}";
            lock (locker)
            {
                vertices.Add(new Vertex2(X, Y));
            }
        };
        RenderDevice.MouseLeftBtnUp    += (s, e) => { };
        RenderDevice.MouseRightBtnDown += (s, e) => {
            DVector2 norm = NormalizeCoords(e.Location.X, e.Location.Y);

            double X = (norm.X - ShiftX) * Scale;
            double Y = (norm.Y - ShiftY) * Scale;

            foreach (Vertex2 v in vertices)
            {
                double dx = v.Point.X - X;
                double dy = v.Point.Y - Y;

                double r = Math.Sqrt(dx * dx + dy * dy);

                double radius = NormalizeDistance(VertexSize) * Scale;

                if (r < radius)
                {
                    ActiveVertex = v;
                    return;
                }
            }
        };

        RenderDevice.MouseRightBtnUp += (s, e) => {
            ActiveVertex = null;
            Pos          = new DVector2(0.0, 0.0);
        };
        RenderDevice.MouseMove += (s, e) => {
            MousePosition = new DVector2(e.Location.X + e.MovDeltaX, e.Location.Y + e.MovDeltaY);

            if (ActiveVertex != null)
            {
                double dx = NormalizeDistance(e.MovDeltaX) * Scale;
                double dy = NormalizeDistance(e.MovDeltaY) * Scale;

                if (e.MovDeltaX < 0)
                {
                    dx = -dx;
                }
                if (e.MovDeltaY > 0)
                {
                    dy = -dy;
                }

                double newX = ActiveVertex.Point.X + dx;
                double newY = ActiveVertex.Point.Y + dy;
                ActiveVertex.Point = new DVector2(newX, newY);

                Pos = ActiveVertex.Point;
            }
        };

        // Реализация управления клавиатурой
        RenderDevice.HotkeyRegister(Keys.Up, (s, e) => ShiftY                  += 0.05);
        RenderDevice.HotkeyRegister(Keys.Down, (s, e) => ShiftY                -= 0.05);
        RenderDevice.HotkeyRegister(Keys.Left, (s, e) => ShiftX                -= 0.05);
        RenderDevice.HotkeyRegister(Keys.Right, (s, e) => ShiftX               += 0.05);
        RenderDevice.HotkeyRegister(KeyMod.Shift, Keys.Up, (s, e) => ShiftY    += 0.1);
        RenderDevice.HotkeyRegister(KeyMod.Shift, Keys.Down, (s, e) => ShiftY  -= 0.1);
        RenderDevice.HotkeyRegister(KeyMod.Shift, Keys.Left, (s, e) => ShiftX  -= 0.1);
        RenderDevice.HotkeyRegister(KeyMod.Shift, Keys.Right, (s, e) => ShiftX += 0.1);

        RenderDevice.HotkeyRegister(Keys.C, (s, e) => {
            DVector2 vec = NormalizeCoords(MousePosition.X, MousePosition.Y);

            ShiftX = -vec.X + ShiftX;
            ShiftY = -vec.Y + ShiftY;
        });


        RenderDevice.MouseWheel += (s, e) => {
            float DeltaScale = -e.Delta / 10000.0f;
            Scale += DeltaScale;
        };
        RenderDevice.MouseMoveWithMiddleBtnDown += (s, e) => {
            double dx = NormalizeDistance(e.MovDeltaX);
            double dy = NormalizeDistance(e.MovDeltaY);

            if (e.MovDeltaX < 0)
            {
                dx = -dx;
            }
            if (e.MovDeltaY > 0)
            {
                dy = -dy;
            }

            ShiftX += dx;
            ShiftY += dy;
        };

        #endregion

        spline = new CatmullRomSpline(vertices, false, 1.0 / ApproxLevel);

        #region  Инициализация OGL и параметров рендера -----------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            gl.FrontFace(OpenGL.GL_CCW);
            gl.Enable(OpenGL.GL_CULL_FACE);
            gl.CullFace(OpenGL.GL_BACK);

            gl.ClearColor(0, 0, 0, 0);

            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.DepthFunc(OpenGL.GL_LEQUAL);
            gl.ClearDepth(1.0f);    // 0 - ближе, 1 - далеко
            gl.ClearStencil(0);
        });
        #endregion

        #region Обновление матрицы проекции при изменении размеров окна и запуске приложения ----------------
        RenderDevice.Resized += (s, e) =>
        {
            var gl = e.gl;

            UpdateProjectionMatrix(gl);
        };
        #endregion
    }
Beispiel #9
0
    protected override void OnMainWindowLoad(object sender, EventArgs args)
    {
        base.VSPanelWidth = 260;
        base.ValueStorage.RightColWidth = 60;
        base.RenderDevice.VSync         = 1;

        #region Обработчики событий мыши и клавиатуры -------------------------------------------------------
        RenderDevice.MouseMoveWithLeftBtnDown += (s, e) => Rotation += new DVector3(e.MovDeltaY, e.MovDeltaX, 0);

        RenderDevice.MouseMoveWithRightBtnDown += (s, e) => {
            double W = base.RenderDevice.Width;
            double H = base.RenderDevice.Height;

            double AspectRatio = W / H;

            if (W > H)
            {
                ShiftX += ((double)e.MovDeltaX / W * 2) * AspectRatio;
                ShiftY -= (double)e.MovDeltaY / H * 2;
            }
            else
            {
                ShiftX += (double)e.MovDeltaX / W * 2;
                ShiftY -= ((double)e.MovDeltaY / H * 2) / AspectRatio;
            }
        };
        #endregion

        // Как было отмеченно выше вся работа связанная с OGL должна выполнятся в одном потоке. Тут работа с OGL
        // осуществляется в отдельном потоке, а метод OnMainWindowLoad() является событием возбуждаемым потоком
        // пользовательского интерфейса (UI). Поэтой причине весь код ниже добавляется в диспетчер устройства
        // вывода (метод AddScheduleTask() объекта RenderDevice) и выполняется ассинхронно в контексте потока
        // OGL. Сам диспетчер является очередью типа FIFO (First In First Out - т.е. задания обрабатываются
        // строго в порядке их поступления) и гарантирует, что все задания добавленные в OnMainWindowLoad()
        // будут выполнены до первого вызова метода OnDeviceUpdate() (aka OnPaint)

        InclinedCylinder();

        #region  Инициализация OGL и параметров рендера -----------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            gl.FrontFace(OpenGL.GL_CCW);
            gl.Enable(OpenGL.GL_CULL_FACE);
            gl.CullFace(OpenGL.GL_BACK);

            gl.ClearColor(0, 0, 0, 0);

            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.DepthFunc(OpenGL.GL_LEQUAL);
            gl.ClearDepth(1.0f);    // 0 - ближе, 1 - далеко
            gl.ClearStencil(0);
        });
        #endregion

        #region Инициализация буфера вершин -----------------------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            uint[] VertexVBOIDtempArray = new uint[1];
            gl.GenBuffers(1, VertexVBOIDtempArray);

            VertexVBOID = VertexVBOIDtempArray[0];

            uint[] IndexVBOIDtempArray = new uint[1];
            gl.GenBuffers(1, IndexVBOIDtempArray);

            IndexVBOID = IndexVBOIDtempArray[0];
        }, this);
        #endregion

        #region Уничтожение буфера вершин по завершению работы OGL ------------------------------------------
        RenderDevice.Closed += (s, e) => // Событие выполняется в контексте потока OGL при завершении работы
        {
            var gl = e.gl;

            gl.DeleteBuffers(2, new uint[2] {
                VertexVBOID, IndexVBOID
            });
        };
        #endregion

        #region Обновление матрицы проекции при изменении размеров окна и запуске приложения ----------------
        RenderDevice.Resized += (s, e) =>
        {
            var gl = e.gl;

            UpdateProjectionMatrix(gl);
        };
        #endregion
    }
Beispiel #10
0
    protected override void OnMainWindowLoad(object sender, EventArgs args)
    {
        base.VSPanelWidth = 260;
        base.ValueStorage.RightColWidth = 60;
        base.RenderDevice.VSync         = 1;

        #region Обработчики событий мыши и клавиатуры -------------------------------------------------------
        RenderDevice.MouseMoveWithRightBtnDown += (s, e) => Rotation += new DVector3(e.MovDeltaY, e.MovDeltaX, 0);

        RenderDevice.MouseMoveWithMiddleBtnDown += (s, e) => {
            double H = base.RenderDevice.Height;
            double W = base.RenderDevice.Width;

            double AspectRatio = W / H;

            if (W > H)
            {
                Shift = new DVector2(Shift.X + 2 * e.MovDeltaX / W * AspectRatio, Shift.Y - 2 * (double)e.MovDeltaY / H);
            }
            else
            {
                Shift = new DVector2(Shift.X + 2 * e.MovDeltaX / W, Shift.Y - 2 * (double)e.MovDeltaY / H / AspectRatio);
            }
        };

        RenderDevice.MouseLeftBtnDown += (s, e) => {
            DVector2 norm = NormalizeCoords(e.Location.X, e.Location.Y);

            double H = base.RenderDevice.Height;
            double W = base.RenderDevice.Width;

            double AspectRatio = W / H;

            double X, Y;
            if (W > H)
            {
                X = (norm.X) / AspectRatio;
                Y = norm.Y;
            }
            else
            {
                X = norm.X;
                Y = (norm.Y) * AspectRatio;
            }

            DVector4 mousePos = new DVector4(X, Y, 0.0, 0.0);

            lock (ActiveVertexLocker)
            {
                ActiveVertex = FindClosestVertex(transformationMatrix, mousePos);

                if (ActiveVertex != null)
                {
                    ActiveVertexPosition = ActiveVertex.Point;
                }
                else
                {
                    ActiveVertexPosition = DVector3.Zero;
                }
            }
        };

        RenderDevice.MouseLeftBtnUp    += (s, e) => { };
        RenderDevice.MouseRightBtnDown += (s, e) => {
        };

        RenderDevice.MouseRightBtnUp += (s, e) =>
        {
        };
        RenderDevice.MouseMove += (s, e) =>
        {
        };

        #endregion


        #region  Инициализация OGL и параметров рендера -----------------------------------------------------
        RenderDevice.AddScheduleTask((gl, s) =>
        {
            gl.FrontFace(OpenGL.GL_CCW);
            gl.Enable(OpenGL.GL_CULL_FACE);
            gl.CullFace(OpenGL.GL_BACK);

            gl.ClearColor(0, 0, 0, 0);

            gl.Enable(OpenGL.GL_DEPTH_TEST);
            gl.DepthFunc(OpenGL.GL_LEQUAL);
            gl.ClearDepth(1.0f);    // 0 - ближе, 1 - далеко
            gl.ClearStencil(0);
        });
        #endregion

        #region Обновление матрицы проекции при изменении размеров окна и запуске приложения ----------------
        RenderDevice.Resized += (s, e) =>
        {
            var gl = e.gl;

            UpdateProjectionMatrix(gl);
        };
        #endregion

        surface = new CoonsSurface(Prefix + ".txt");

        surface.ComputeSurface(ApproxLevel);
    }