/// <summary>
        /// Возвращает истину при пересечении плоскости и линии
        /// </summary>
        /// <param name="vPolygon">Треугольник (плоскость)</param>
        /// <param name="vLine">Линия</param>
        /// <returns>Истина при пересечении, иначе - ложь</returns>
        public static bool intersectedPlane(Vector3[] vPolygon, Vector3[] vLine, Vector3 vNormal, ref float originDistance)
        {
            bool  intersection = false;
            float distance1 = 0, distance2 = 0;                        // Дистанция 2х точек линии

            vNormal = VectorMathOperations.GetNormalToPlane(vPolygon); // Рассчитываем нормаль плоскости

            // Найдем дистанцию плоскости от начала координат:
            originDistance = planeDistance(vNormal, vPolygon[0]);

            // Получим дистанции от первой и второй точек:
            distance1 = ((vNormal.X * vLine[0].X) +                    // Ax +
                         (vNormal.Y * vLine[0].Y) +                    // Bx +
                         (vNormal.Z * vLine[0].Z)) + originDistance;   // Cz + D

            distance2 = ((vNormal.X * vLine[1].X) +                    // Ax +
                         (vNormal.Y * vLine[1].Y) +                    // Bx +
                         (vNormal.Z * vLine[1].Z)) + originDistance;   // Cz + D


            // Проверим на пересечение
            if (distance1 * distance2 >= 0)
            {
                intersection = false;
            }
            else
            {
                intersection = true;
            }
            return(intersection);
        }
        public static BoneTransform SLerp(BoneTransform lhv, BoneTransform rhv, float blend)
        {
            Vector3    lerpPosition = VectorMathOperations.LerpVector(blend, 0, 1, lhv.m_toBoneTranslation, rhv.m_toBoneTranslation);
            Vector3    lerpScale    = VectorMathOperations.LerpVector(blend, 0, 1, lhv.m_toBoneScale, rhv.m_toBoneScale);
            Quaternion lerpRotation = Quaternion.Slerp(lhv.m_toBoneRotation, rhv.m_toBoneRotation, blend);

            return(new BoneTransform(lerpRotation, lerpPosition, lerpScale));
        }
Example #3
0
 public void MultMatrix(ref Matrix4 modelMatrix)
 {
     for (Int32 i = 0; i < Vertices.Length / 3; i++)
     {
         Vector4 vertex = new Vector4(Vertices[i, 0], Vertices[i, 1], Vertices[i, 2], 1.0f);
         vertex = VectorMathOperations.multMatrix(modelMatrix, vertex);
         this.Vertices[i, 0] = vertex.X;
         this.Vertices[i, 1] = vertex.Y;
         this.Vertices[i, 2] = vertex.Z;
         if (_normals != null)
         {
             Vector4 normal = new Vector4(Normals[i, 0], Normals[i, 1], Normals[i, 2], 0.0f);
             normal             = VectorMathOperations.multMatrix(modelMatrix, normal);
             this.Normals[i, 0] = normal.X;
             this.Normals[i, 1] = normal.Y;
             this.Normals[i, 2] = normal.Z;
         }
     }
 }
        private void UpdateRotationMatrix(Int32 deltaX, Int32 deltaY)
        {
            m_eyeSpaceForwardVector = VectorMathOperations.multMatrix(m_rotationMatrix, m_localSpaceForwardVector).Normalized();
            m_eyeSpaceRightVector   = Vector3.Cross(m_eyeSpaceForwardVector, m_localSpaceUpVector).Normalized();

            float anglePitch = deltaY * rotateSensetivity;
            float angleYaw   = deltaX * rotateSensetivity;

            Matrix3 rotatePitch = Matrix3.CreateFromAxisAngle(m_eyeSpaceRightVector, MathHelper.DegreesToRadians(anglePitch));
            Matrix3 rotateYaw   = Matrix3.CreateRotationY(MathHelper.DegreesToRadians(angleYaw));

            Matrix3 tempRotationMatrix = Matrix3.Identity;

            tempRotationMatrix *= rotateYaw;
            tempRotationMatrix *= rotatePitch;

            m_rotationMatrix = tempRotationMatrix * m_rotationMatrix;

            bTransformationDirty = true;

            //Console.Clear();
            //pitch = (float)Math.Atan2(-rotationMatrix[2, 0], Math.Sqrt(rotationMatrix[2, 1] * rotationMatrix[2, 1] + rotationMatrix[2, 2] * rotationMatrix[2, 2]));
            //Console.WriteLine(pitch);
        }
        static public VertexArrayObject getTerrainAttributes(TableGrid LandscapeMap, Int32 normalSmoothLvl)
        {
            Int32 VERTEX_COUNT = LandscapeMap.TableSize - 1;
            float x, z;

            float[,] vertices  = new float[(VERTEX_COUNT * VERTEX_COUNT) * 6, 3];
            float[,] texCoords = new float[(VERTEX_COUNT * VERTEX_COUNT) * 6, 2];
            float[,] normals   = new float[(VERTEX_COUNT * VERTEX_COUNT) * 6, 3];
            Int32   vertexPointer = 0;
            Vector3 tempNormal;

            Vector3[,] normalMatrix = new Vector3[LandscapeMap.TableSize, LandscapeMap.TableSize];

            for (Int32 i = 0; i < LandscapeMap.TableSize - 1; i++)
            {
                for (Int32 j = 0; j < LandscapeMap.TableSize - 1; j++)
                {
                    x = i * (float)LandscapeMap.GridStep;
                    z = j * (float)LandscapeMap.GridStep;

                    vertices[vertexPointer, 0] = x;
                    vertices[vertexPointer, 1] = LandscapeMap.Table[i, j];
                    vertices[vertexPointer, 2] = z;
                    tempNormal = VectorMathOperations.GetNormalToPlane(new Vector3[3] {
                        new Vector3(x, LandscapeMap.Table[i, j], z),
                        new Vector3(x, LandscapeMap.Table[i, j + 1], z + (float)LandscapeMap.GridStep),
                        new Vector3(x + (float)LandscapeMap.GridStep, LandscapeMap.Table[i + 1, j], z)
                    });
                    normalMatrix[i, j] = tempNormal;
                    //tempNormal = getLandscapeNormal(i, j);
                    normals[vertexPointer, 0]   = tempNormal.X;
                    normals[vertexPointer, 1]   = tempNormal.Y;
                    normals[vertexPointer, 2]   = tempNormal.Z;
                    texCoords[vertexPointer, 0] = vertices[vertexPointer, 0] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    texCoords[vertexPointer, 1] = vertices[vertexPointer, 2] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    vertices[vertexPointer + 1, 0] = x;
                    vertices[vertexPointer + 1, 1] = LandscapeMap.Table[i, j + 1];
                    vertices[vertexPointer + 1, 2] = z + (float)LandscapeMap.GridStep;
                    tempNormal = VectorMathOperations.GetNormalToPlane(new Vector3[3] {
                        new Vector3(x, LandscapeMap.Table[i, j + 1], z + (float)LandscapeMap.GridStep),
                        new Vector3(x + (float)LandscapeMap.GridStep, LandscapeMap.Table[i + 1, j], z),
                        new Vector3(x, LandscapeMap.Table[i, j], z)
                    });
                    normalMatrix[i, j + 1] = tempNormal;
                    //tempNormal = getLandscapeNormal(i, j + 1);
                    normals[vertexPointer + 1, 0]   = tempNormal.X;
                    normals[vertexPointer + 1, 1]   = tempNormal.Y;
                    normals[vertexPointer + 1, 2]   = tempNormal.Z;
                    texCoords[vertexPointer + 1, 0] = vertices[vertexPointer + 1, 0] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    texCoords[vertexPointer + 1, 1] = vertices[vertexPointer + 1, 2] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    vertices[vertexPointer + 2, 0] = x + (float)LandscapeMap.GridStep;
                    vertices[vertexPointer + 2, 1] = LandscapeMap.Table[i + 1, j];
                    vertices[vertexPointer + 2, 2] = z;
                    tempNormal = VectorMathOperations.GetNormalToPlane(new Vector3[3] {
                        new Vector3(x + (float)LandscapeMap.GridStep, LandscapeMap.Table[i + 1, j], z),
                        new Vector3(x, LandscapeMap.Table[i, j], z),
                        new Vector3(x, LandscapeMap.Table[i, j + 1], z + (float)LandscapeMap.GridStep)
                    });
                    normalMatrix[i + 1, j] = tempNormal;
                    //tempNormal = getLandscapeNormal(i + 1, j);
                    normals[vertexPointer + 2, 0]   = tempNormal.X;
                    normals[vertexPointer + 2, 1]   = tempNormal.Y;
                    normals[vertexPointer + 2, 2]   = tempNormal.Z;
                    texCoords[vertexPointer + 2, 0] = vertices[vertexPointer + 2, 0] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    texCoords[vertexPointer + 2, 1] = vertices[vertexPointer + 2, 2] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    vertices[vertexPointer + 3, 0]  = x + (float)LandscapeMap.GridStep;
                    vertices[vertexPointer + 3, 1]  = LandscapeMap.Table[i + 1, j];
                    vertices[vertexPointer + 3, 2]  = z;
                    normals[vertexPointer + 3, 0]   = normals[vertexPointer + 2, 0];
                    normals[vertexPointer + 3, 1]   = normals[vertexPointer + 2, 1];
                    normals[vertexPointer + 3, 2]   = normals[vertexPointer + 2, 2];
                    texCoords[vertexPointer + 3, 0] = vertices[vertexPointer + 3, 0] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    texCoords[vertexPointer + 3, 1] = vertices[vertexPointer + 3, 2] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    vertices[vertexPointer + 4, 0]  = x;
                    vertices[vertexPointer + 4, 1]  = LandscapeMap.Table[i, j + 1];
                    vertices[vertexPointer + 4, 2]  = z + (float)LandscapeMap.GridStep;
                    normals[vertexPointer + 4, 0]   = normals[vertexPointer + 1, 0];
                    normals[vertexPointer + 4, 1]   = normals[vertexPointer + 1, 1];
                    normals[vertexPointer + 4, 2]   = normals[vertexPointer + 1, 2];
                    texCoords[vertexPointer + 4, 0] = vertices[vertexPointer + 4, 0] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    texCoords[vertexPointer + 4, 1] = vertices[vertexPointer + 4, 2] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    vertices[vertexPointer + 5, 0] = x + (float)LandscapeMap.GridStep;
                    vertices[vertexPointer + 5, 1] = LandscapeMap.Table[i + 1, j + 1];
                    vertices[vertexPointer + 5, 2] = z + (float)LandscapeMap.GridStep;
                    tempNormal = VectorMathOperations.GetNormalToPlane(new Vector3[3] {
                        new Vector3(x + (float)LandscapeMap.GridStep, LandscapeMap.Table[i + 1, j + 1], z + (float)LandscapeMap.GridStep),
                        new Vector3(x + (float)LandscapeMap.GridStep, LandscapeMap.Table[i + 1, j], z),
                        new Vector3(x, LandscapeMap.Table[i, j + 1], z + (float)LandscapeMap.GridStep)
                    });
                    normalMatrix[i + 1, j + 1] = tempNormal;
                    //tempNormal = getLandscapeNormal(i + 1, j + 1);
                    normals[vertexPointer + 5, 0]   = tempNormal.X;
                    normals[vertexPointer + 5, 1]   = tempNormal.Y;
                    normals[vertexPointer + 5, 2]   = tempNormal.Z;
                    texCoords[vertexPointer + 5, 0] = vertices[vertexPointer + 5, 0] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    texCoords[vertexPointer + 5, 1] = vertices[vertexPointer + 5, 2] / (float)(LandscapeMap.GridStep * LandscapeMap.TableSize);
                    //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
                    vertexPointer += 6;
                }
            }
            // Making smooth normals
            vertexPointer = 0;
            for (Int32 i = 0; i < LandscapeMap.TableSize - 1; i++)
            {
                for (Int32 j = 0; j < LandscapeMap.TableSize - 1; j++)
                {
                    tempNormal = getLandscapeSmoothNormal(LandscapeMap, normalMatrix, i, j, normalSmoothLvl);
                    normals[vertexPointer, 0] = tempNormal.X;
                    normals[vertexPointer, 1] = tempNormal.Y;
                    normals[vertexPointer, 2] = tempNormal.Z;
                    tempNormal = getLandscapeSmoothNormal(LandscapeMap, normalMatrix, i, j + 1, normalSmoothLvl);
                    normals[vertexPointer + 1, 0] = tempNormal.X;
                    normals[vertexPointer + 1, 1] = tempNormal.Y;
                    normals[vertexPointer + 1, 2] = tempNormal.Z;
                    tempNormal = getLandscapeSmoothNormal(LandscapeMap, normalMatrix, i + 1, j, normalSmoothLvl);
                    normals[vertexPointer + 2, 0] = tempNormal.X;
                    normals[vertexPointer + 2, 1] = tempNormal.Y;
                    normals[vertexPointer + 2, 2] = tempNormal.Z;
                    normals[vertexPointer + 3, 0] = normals[vertexPointer + 2, 0];
                    normals[vertexPointer + 3, 1] = normals[vertexPointer + 2, 1];
                    normals[vertexPointer + 3, 2] = normals[vertexPointer + 2, 2];
                    normals[vertexPointer + 4, 0] = normals[vertexPointer + 1, 0];
                    normals[vertexPointer + 4, 1] = normals[vertexPointer + 1, 1];
                    normals[vertexPointer + 4, 2] = normals[vertexPointer + 1, 2];
                    tempNormal = getLandscapeSmoothNormal(LandscapeMap, normalMatrix, i + 1, j + 1, normalSmoothLvl);
                    normals[vertexPointer + 5, 0] = tempNormal.X;
                    normals[vertexPointer + 5, 1] = tempNormal.Y;
                    normals[vertexPointer + 5, 2] = tempNormal.Z;
                    vertexPointer += 6;
                }
            }

            VertexBufferObjectTwoDimension <float> verticesVBO   = new VertexBufferObjectTwoDimension <float>(vertices, OpenTK.Graphics.OpenGL.BufferTarget.ArrayBuffer, 0, 3, VertexBufferObjectBase.DataCarryFlag.Invalidate);
            VertexBufferObjectTwoDimension <float> normalsVBO    = new VertexBufferObjectTwoDimension <float>(normals, OpenTK.Graphics.OpenGL.BufferTarget.ArrayBuffer, 1, 3, VertexBufferObjectBase.DataCarryFlag.Invalidate);
            VertexBufferObjectTwoDimension <float> texCoordsVBO  = new VertexBufferObjectTwoDimension <float>(texCoords, OpenTK.Graphics.OpenGL.BufferTarget.ArrayBuffer, 2, 2, VertexBufferObjectBase.DataCarryFlag.Invalidate);
            VertexBufferObjectTwoDimension <float> tangentsVBO   = new VertexBufferObjectTwoDimension <float>(AdditionalVertexInfoCreator.CreateTangentVertices(vertices, texCoords), OpenTK.Graphics.OpenGL.BufferTarget.ArrayBuffer, 4, 3, VertexBufferObjectBase.DataCarryFlag.Invalidate);
            VertexBufferObjectTwoDimension <float> bitangentsVBO = new VertexBufferObjectTwoDimension <float>(AdditionalVertexInfoCreator.CreateBitangentVertices(vertices, texCoords), OpenTK.Graphics.OpenGL.BufferTarget.ArrayBuffer, 5, 3, VertexBufferObjectBase.DataCarryFlag.Invalidate);

            VertexArrayObject vao = new VertexArrayObject();

            vao.AddVBO(verticesVBO, normalsVBO, texCoordsVBO, tangentsVBO, bitangentsVBO);
            vao.BindBuffersToVao();

            return(vao);
        }
        ////////////////////////////// SPHERE POLYGON COLLISION """""""""\\*
        /////
        /////	 возвращает true если сфера пересекает переданный полигон.
        /////
        ////////////////////////////// SPHERE POLYGON COLLISION """""""""\\*

        public static bool SpherePolygonCollision(Vector3[] vPolygon, Vector3 vCenter, Int32 vertexCount, float radius)
        {
            //
            // 1) Сначала нужно проверить, пересекается ли сфера с плоскостью, на которой находится
            //    полигон. Помните, что плоскости бесконечны, и сфера может быть хоть в пятистах
            //    единицах от полигона, если сфера пересекает его плоскость - триггер сработает.
            //    Нам нужно написать функцию, возвращающую положение сферы: либо она полностью
            //    с одной стороны плоскости, либо с другой, либо пересекает плоскость.
            //    Для этого мы создали функцию ClassifySphere(), которая возвращает BEHIND, FRONT
            //    или INTERSECTS. Если она вернёт INTERSECTS, переходим ко второму шагу, иначе - мы
            //    не пересекаем плоскость полигона.
            //
            //  2) Второй шаг - получить точку пересечения. Это одна из хитрых частей. Мы знаем,
            //    что имея точку пересечения с плоскостью, нужно просто вызвать функцию InsidePolygon(),
            //    чтобы увидеть, находится ли эта точка внутри полигона, точно так же, как мы делали
            //    в уроке "Коллизия линии и полигона". Итак, как получить точку пересечения? Это
            //    не так просто, как кажется. Поскольку на сфере может распологатся бесконечное
            //    число точек, могут быть миллионы точек пересечения. Мы попробуем немного другой путь.
            //    Мы знаем, что можем найти нормаль полигона, что скажет нам направление, куда
            //    он "смотрит". ClassifyPoly() кроме всего прочего вернёт дистанцию от центра сферы до
            //    плоскости. И если мы умножим нормаль на эту дистанцию, то получим некое смещение.
            //    Это смещение может затем быть вычтено из центра сферы. Хотите верьте, хотите нет,
            //    но теперь у нас есть точка на плоскости в направлении плоскости. Обычно эта точка
            //    пересечения работает хорошо, но если мы пересечем ребра полигона, она не сработает.
            //    То, что мы только что сделали, называется "проекция центра сферы на плоскость".
            //    Другой путь - "выстрелить" луч от центра сферы в направлении, противоположном
            //    нормали плоскости, тогда мы найдем точку пересечения линии (этого луча) и плоскости.
            //    Мой способ занимает 3 умножения и одно вычитание. Выбирайте сами.
            //
            // 3) Имея нашу псевдо-точку пересечения, просто передаём её в InsidePolygon(),
            //    вместе с вершинами полигона и их числом. Функция вернёт true, если точка
            //    пересечения находится внутри полигона. Запомните, одно то, что функция
            //    вернёт false, не значит, что мы на этом остановимся! Если мы ещё не "пересеклись",
            //    переходим к шагу 4.
            //
            // 4) Если мы дошли досюда, значит, мы нашли точку пересечения, и она находится
            //    вне периметра полигона. Как так? Легко. Подумайте, если центр сферы находится
            //    вне треугольника, но есть пересечение - остаётся ещё её радиус. Последняя
            //    проверка нуждается в нахождении точка на каждом ребре полигона, которая
            //    ближе всего к центру сферы. У нас есть урок "ближайшая точка на линии", так что
            //    убедитесь, что вы его поняли, прежде, чем идти дальше. Если мы имеем дело
            //    с треугольником, нужно пройти три ребра и найти на них ближайшие точки к центру
            //    сферы. После этого рассчитываем дистанцию от этих точек до центра сферы. Если
            //    дистанция меньше, чем радиус, есть пересечение. Этот способ очень быстр.
            //    Вым не нужно рассчитывать всегда все три ребра, так как первая или вторая
            //    дистанция может быть меньше радиуса, и остальные рассчеты можно будет не производить.
            //
            //    Это было вступление, *уфф!*. Надеюсь, вам ещё не хочется плакать от такого обилия
            //    теории, так как код на самом деле будет не слишком большим.


            // 1) ШАГ ОДИН - Найдем положение сферы

            // Сначала найдем нормаль полигона
            Vector3 vNormal = VectorMathOperations.GetNormalToPlane(vPolygon);

            // Переменная для хранения дистанции от сферы
            float distance = 0.0f;

            // Здесь мы определяем, находится ли сфера спереди, сзади плоскости, или пересекает её.
            // Передаём центр сферы, нормаль полигона, точку на плоскости (любую вершину), радиус
            // сферы и пустой float для сохранения дистанции.
            Int32 classification = ClassifySphere(vCenter, vNormal, vPolygon[0], radius, ref distance);

            // Если сфера пересекает плоскость полигона, нам нужно проверить, пересекает ли
            // она сам полигон.
            if (classification == 1)
            {
                // 2) ШАГ ДВА - Находим псевдо точку пересечения.

                // Теперь нужно спроецировать центр сфера на плоскость полигона, в направлении
                // его номали. Это делается умножением нормали на расстояние от центра сферы
                // до плоскости. Расстояние мы получили из ClassifySphere() только что.
                // Если вы не понимаете суть проекции, представьте её примерно так:
                // "я стартую из центра сферы и двигаюсь в направлении плоскости вдоль её нормали
                // Когда я должен остановится? Тогда, когда моя дистанция от центра сферы станет
                // равной дистанции от центра сферы до плоскости."
                Vector3 vOffset = new Vector3(vNormal.X * distance, vNormal.Y * distance, vNormal.Z * distance);


                // Получив смещение "offset", просто вычитаем его из центра сферы. "vPosition"
                // теперь точка, лежащая на плоскости полигона. Внутри ли она полигона - это
                // другой вопрос.
                Vector3 vPosition = vCenter - vOffset;

                // 3) ШАГ ТРИ - Проверим, находится ли точка пересечения внутри полигона

                //  Если точка пересечения внутри
                // полигона, ф-я вернёт true, иначе false.
                if (insidePolygon(vPosition, vPolygon, vertexCount))
                {
                    return(true); // Есть пересечение!
                }
                else              // Иначе
                {
                    // 4) ШАГ ЧЕТЫРЕ - Проверим, пересекает ли сфера рёбра треугольника

                    // Если мы дошли досюда, центр сферы находится вне треугольника.
                    // Если хоть одна часть сферы пересекает полигон, у нас есть пересечение.
                    // Нам нужно проверить расстояние от центра сферы до ближайшей точки на полигоне.
                    if (EdgeSphereCollision(vCenter, vPolygon, vertexCount, radius))
                    {
                        return(true);    // We collided!
                    }
                }
            }

            // Если мы здесь, пересечения нет
            return(false);
        }