ruggaraxe ruggaraxe

Jusper, Отлично пишите! :)

Jusper Jusper

Я вам еще не закончил писать обратную связь по боевке, есть много вещей которые немного смутили, но они поправимы. Завтра, если перестанут дергать - чиркану. Спасибо за демку!

Jusper Jusper

ruggaraxe,

Да, в этом плане все ок. Логично, что графен на старой машине, если не упарываться, не взлетит. Но я рад, что это было не 5 фпс, как даже в некоторых АА (типа Pillars of Eternity в некоторых схватках...

Jusper Jusper

ruggaraxe,

Подкреплю ее к публикации.

ruggaraxe ruggaraxe

Jusper, вот ссылка на анкету (я затупил со ссылкой с топике, сорри)
https://docs.google.com/forms/d/e/1FAIpQLSd_Wn53lJFrnfGpWI2IX...

ruggaraxe ruggaraxe

Jusper, честно говоря, да на 800х600 даже не проверяли... :) сорри. Ориентировались на FullHD и выше. Хотя над интерфейсом конечно же надо еще хорошенько поработать.
Тултипы постараемся сделать обязательно к следующей версии...

Jusper Jusper

GenElCon,

4x стратегия, понятно.

GenElCon GenElCon

Jusper,

Наверное. В прошлом они сделали Endless Legend - посмотри и сразу станет ясно в какую сторону они работают.

Jusper Jusper

GenElCon,

Я не очень понял по трейлеру геймплей. Это что-то типа цивы? Или это RTS?

GenElCon GenElCon

Humankind от разработчиков Endless Legends (и Space, но тут важно именно Legends).
А также согревающие сердца олдов трейлеры Port Royal 4 и Knights of Honor.

Jusper Jusper

Похвалю темную атмосферу, отличную работу с освещением, тенями и шейдерами. Происходящее на экране корректно задает атмосферу до тех пор, пока не начнется сам экшон, об это напишу далее. Управление персонажем отзывчивое...

Jusper Jusper

Первое, оно же самое тяжелое - UI. Я конечно, понимаю, что 800x600 совсем уже не в моде (завтра проверю на нормальной широформатной машине). Заблюренный текст я еще прочитать могу, но вот конкретно размер его крайне мал...

...
Jusper Jusper

ruggaraxe, я поиграл на старом маке 2012 года (Macbook Pro, Intel HD 4000), рад что с учетом довольно нагруженной по свету и теням картинке игруля не лагает как последняя сволочь (лагает конечно, но очень терпимо...

Jusper Jusper

Вот тут можно посмотреть игровой процесс. Видно, что в Новиграде просаживается FPS.

Jusper Jusper

С учетом тотального количества наигранных на свиче часов, думаю, что именно Switch станет для меня платформой, где я пройду Ведьмака.

Jusper Jusper

alexprey, это первое. Второе это постэффект, которыЙ засвечивает весь песок.

alexprey alexprey

Jusper,

Да, по мне так перебор с интенсивностью освещения

alexprey alexprey

Jusper, в игре используется таже моделька для юнита, только вид сверху)

Jusper Jusper

Пацаны, я опоздал.

Слэш Полигон в эфире.

Логотип проекта Unity

Класс с математикой

Пишу сижу последние дни всякую простейшую математику, которая часто юзается.

В итоге вышел вот такой класс:

using System;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEngine;

public static class CustomMath
{
    //Возвращает индекс минимального элемента
    public static int MinIndex(float[] values)
    {
        return GetABResultIndex<float>(values, (a, b) => a > b, f => true);
    }

    //Возвращает индекс минимального элемента, при том у элемента должно выполнять некоторое условие
    public static int MinIndex(float[] values, Predicate<float> condition)
    {
        return GetABResultIndex<float>(values, (a, b) => a > b, condition);
    }

    //Возвращает индекс максимального элемента
    public static int MaxIndex(float[] values)
    {
        return GetABResultIndex<float>(values, (a, b) => a < b, f => true);
    }

    //Возвращает индекс минимального элемента, при том у элемента должно выполнять некоторое условие
    public static int MaxIndex(float[] values, Predicate<float> condition)
    {
        return GetABResultIndex<float>(values, (a, b) => a < b, condition);
    }

    private static int GetABResultIndex<T>(T[] values, Func<T, T, bool> conditionAB, Predicate<T> conditionElement)
    {
        var resultIndex = -1;
        for (int i = 0; i < values.Length; i++)
        {
            if ((resultIndex == -1 || conditionAB(values[resultIndex], values[i])) && conditionElement(values[i]))
                resultIndex = i;
        }
        return -1;
    }

    //Функции округления тупо продублированы с понятными мне именами

    public static float Round(float value)
    {
        return Mathf.Round(value);
    }

    public static float RoundMin(float value)
    {
        return Mathf.Floor(value);
    }

    public static float RoundMax(float value)
    {
        return Mathf.Ceil(value);
    }

    public static float RoundToInt(float value)
    {
        return Mathf.RoundToInt(value);
    }

    public static float RoundMinToInt(float value)
    {
        return Mathf.FloorToInt(value);
    }

    public static float RoundMaxToInt(float value)
    {
        return Mathf.CeilToInt(value);
    }

    //Округление векторов, епты
    public static Vector3 Round(Vector3 value)
    {
        return new Vector3(Mathf.Round(value.x), Mathf.Round(value.y), Mathf.Round(value.z));
    }

    public static Vector3 RoundMin(Vector3 value)
    {
        return new Vector3(Mathf.Floor(value.x), Mathf.Floor(value.y), Mathf.Floor(value.z));
    }

    public static Vector3 RoundMax(Vector3 value)
    {
        return new Vector3(Mathf.Ceil(value.x), Mathf.Ceil(value.y), Mathf.Ceil(value.z));
    }

    public static Vector2 Round(Vector2 value)
    {
        return new Vector2(Mathf.Round(value.x), Mathf.Round(value.y));
    }

    public static Vector2 RoundMin(Vector2 value)
    {
        return new Vector2(Mathf.Floor(value.x), Mathf.Floor(value.y));
    }

    public static Vector2 RoundMax(Vector2 value)
    {
        return new Vector2(Mathf.Ceil(value.x), Mathf.Ceil(value.y));
    }

    public static Vector3 defaultScale
    {
        get { return new Vector3(1, 1, 1); }
    }

    //Нормали в отрезке

    public static int GetNormal(float value)
    {
        if (value > 0)
            return 1;
        if (value < 0)
            return -1;
        return 0;
    }

    public static int GetNormalPositive(float value)
    {
        if (value > 0)
            return 1;
        return 0;
    }

    public static int GetNormalNegative(float value)
    {
        if (value < 0)
            return -1;
        return 0;
    }

    //Поиск площади фигуры
    public static class Area
    {
        /// <summary>
        /// Формула Герона 
        /// </summary>
        public static float TriangleFromPoints(Vector3 a, Vector3 b, Vector3 c)
        {
            var longitudes = Longitudes(a, b, c);
            var perimeter = longitudes.Sum();
            var p = perimeter/2f;
            var sqrS = p*(p - longitudes[0])*(p - longitudes[1])*(p - longitudes[2]);
            var s = Mathf.Sqrt(sqrS);
            return s;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="aSide"></param>
        /// <param name="bSide"></param>
        /// <param name="cSide"></param>
        /// <returns></returns>
        public static float TriangleFromSides(float aSide, float bSide, float cSide)
        {
            var perimeter = aSide + bSide + cSide;
            var p = perimeter/2f;
            var sqrS = p*(p - aSide)*(p - bSide)*(p - cSide);
            var s = Mathf.Sqrt(sqrS);
            return s;
        }

        public static float TriangleFromPoints_Fast(Vector3 a, Vector3 b, Vector3 c)
        {
            var dir1 = (a - b);
            var dir2 = (c - b);
            return WedgeProduct(dir1, dir2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="side">Длина одной из сторон треугольника</param>
        /// <param name="h">Проведенная к этой длине высота</param>
        /// <returns></returns>
        public static float TriangleFromSideAndHeight(float side, float h)
        {
            return .5f*side*h;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="perimeter"></param>
        /// <param name="r">Радиус вписанной окружности</param>
        /// <returns></returns>
        public static float TriangleFromPerimeterAndInradius(float perimeter, float r)
        {
            var p = perimeter/2f;
            return p*r;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="aSide"></param>
        /// <param name="bSide"></param>
        /// <param name="cSide"></param>
        /// <param name="R">Радиус описанной окружности</param>
        /// <returns></returns>
        public static float TriangleFromSidesAndOutradius(float aSide, float bSide, float cSide, float R)
        {
            return (aSide*bSide*cSide)/(4*R);
        }

        public static float TriangleFromSidesAndAngle(float aSide, float bSide, float angleAB)
        {
            return .5f * aSide * bSide * Degrees.Sin(angleAB);
        }

        public static float SquareFromSide(float side)
        {
            return side*side;
        }

        public static float SquareFromDiagonal(float diagonal)
        {
            return .5f*(diagonal*diagonal);
        }

        public static float RectangleFromSides(float aSide, float bSide)
        {
            return aSide*bSide;
        }

        public static float RectangleFromPoints(Vector3 a, Vector3 b, Vector3 c)
        {
            var aSide = Vector3.Distance(a, b);
            var bSide = Vector3.Distance(b, c);
            return RectangleFromSides(aSide, bSide);
        }

        /// <summary>
        /// Формула площади параллелограмма по длине стороны и высоте.
        /// Площадь параллелограмма равна произведению длины его стороны и длины опущенной на эту сторону высоты.
        /// </summary>
        /// <param name="aSide"></param>
        /// <param name="height"></param>
        /// <returns></returns>
        public static float ParallelogramFromSideAndHeight(float aSide, float height)
        {
            return aSide*height;
        }

        public static float ParallelogramFromPoints(Vector3 a, Vector3 b, Vector3 c)
        {
            var aSide = Vector3.Distance(a, b);
            var bSide = Vector3.Distance(b, c);
            var dirBA = (a - b);
            var dirBC = (c - b);
            var angle = Vector3.Angle(dirBA, dirBC);
            return ParallelogramFromSidesAndAngle(aSide, bSide, angle);
        }

        public static float ParallelogramFromPoints_Fast(Vector3 a, Vector3 b, Vector3 c)
        {
            var dir1 = (a - b);
            var dir2 = (c - b);
            return WedgeProduct(dir1, dir2);
        }

        public static float ParallelogramFromSidesAndAngle(float aSide, float bSide, float angleAB)
        {
            return aSide * bSide * Degrees.Sin(angleAB);
        }

        public static float ParallelogramFromDiagonalAndAngle(float d1, float d2, float angleD1D2)
        {
            return d1 * d2 * Degrees.Sin(angleD1D2);
        }

        public static float CircleFromRadius(float radius)
        {
            return Mathf.PI*(radius*radius);
        }

        public static float CircleFromDiameter(float diameter)
        {
            return .25f * Mathf.PI * (diameter * diameter);
        }

        public static float Ellipse(float radius1, float radius2)
        {
            return Mathf.PI*radius1*radius2;
        }

        public static float TrapezeFromSides(float a, float b, float c, float d)
        {
            var p = (a + b + c + d)/2f;
            var n1 = a + b;
            var n2 = 4 - Mathf.Abs(a - b);
            var n3 = (p - a)*(p - b)*(p - a - c)*(p - a - d);
            var s = (n1/n2)*Mathf.Sqrt(n3);
            return s;
        }

        public static float TrapezeFromBasesAndHeight(float aBase, float bBase, float height)
        {
            return .5f*(aBase + bBase)*height;
        }

        public static float RhombusFromSideAndHeight(float aSide, float height)
        {
            return aSide*height;
        }

        public static float RhombusFromSideAndAngle(float aSide, float angleInDegrees)
        {
            return aSide*aSide*Degrees.Sin(angleInDegrees);
        }

        public static float RhombusFromDiagonals(float diagonal1, float diagonal2)
        {
            return .5f*diagonal1*diagonal2;
        }

        public static float SphereFromRadius(float radius)
        {
            return 4*Mathf.PI*(radius*radius);
        }

        /// <summary>
        /// Все точки должны быть в одной плоскости
        /// </summary>
        /// <param name="points"></param>
        /// <returns></returns>
        public static float PolygonFromPoints_Fast(params Vector2[] points)
        {
            if (points.Length < 3)
                throw new Exception("Need minimum 3 points");
            
            var s = 0f;
            for (int i = 0; i < points.Length; i++)
            {
                var iplus = (i + 1)%points.Length;
                var a = points[i];
                var b = points[iplus];
                var c = new Vector2(b.x, 0);
                var d = new Vector2(a.x, 0);
                s += TrapezeFromBasesAndHeight(a.y, b.y, c.x - d.x);
            }
            return Mathf.Abs(s);
        }

        public static float PolygonFromPoints(params Vector2[] points)
        {
            if (points.Length < 3)
                throw new Exception("Need minimum 3 points");
            var min = points.Min(v => v.y);
            var s = 0f;
            for (int i = 0; i < points.Length; i++)
            {
                var iplus = (i + 1) % points.Length;
                var a = points[i];
                var b = points[iplus];
                var c = new Vector2(b.x, min);
                var d = new Vector2(a.x, min);
                s += TrapezeFromBasesAndHeight(a.y - min, b.y - min, c.x - d.x);
            }
            return Mathf.Abs(s);
        }

    }

    public static class Perimeter
    {
        public static float Points(params Vector3[] points)
        {
            if (points.GetCount() < 3)
                throw new Exception("points.Length need value >= 3");
            return Longitudes(points).Sum();
        }

        public static float Points(params Vector2[] points)
        {
            if (points.GetCount() < 3)
                throw new Exception("points.Length need value >= 3");
            return Longitudes(points).Sum();
        }

        public static float CircleFromRadius(float radius)
        {
            return 2*Mathf.PI * radius;
        }

        public static float CircleFromDiameter(float diameter)
        {
            return diameter * Mathf.PI;
        }

        public static float Sides(params float[] sides)
        {
            if (sides.Length < 3)
                throw new Exception("sides.Length need value >= 3");
            return sides.Sum();
        }

        public static float Rhombus(float aSide)
        {
            return 4*aSide;
        }

        public static float Square(float aSide)
        {
            return 4*aSide;
        }

        public static float Rectangle(float aSide, float bSide)
        {
            return 2*(aSide+bSide);
        }

        public static float Parallelogram(float aSide, float bSide)
        {
            return 2*(aSide*bSide);
        }
    }

    public static class Volume
    {
        public static float Cube(float aSide)
        {
            return aSide*aSide*aSide;
        }

        public static float Prism(float sBase, float height)
        {
            return sBase*height;
        }

        public static float Parallelepiped(Vector3 a, Vector3 b, Vector3 c)
        {
            return Mathf.Abs(TripleScalarProduct(a,b,c));
        }

        public static float Parallelepiped(float sBase, float height)
        {
            return sBase*height;
        }

        public static float Cuboid(float aSide, float bSide, float height)
        {
            return aSide*bSide*height;
        }

        public static float Pyramid(float sBase, float height)
        {
            return (sBase*height)/3f;
        }

        public static float RegularTetrahedron(float aSide)
        {
            var n1 = aSide*aSide*aSide;
            var n2 = Mathf.Sqrt(2);
            return (n1*n2)/12;
        }

        public static float CylinderFromRadius(float radius, float height)
        {
            return Mathf.PI*(radius*radius)*height;
        }

        public static float CylinderFromS(float sBase, float height)
        {
            return sBase * height;
        }

        public static float ConeFromRadius(float radius, float height)
        {
            return CylinderFromRadius(radius, height)/3f;
        }

        public static float ConeFromS(float sBase, float height)
        {
            return CylinderFromS(sBase, height) / 3f;
        }

        public static float Sphere(float radius)
        {
            return 4f/3f*Mathf.PI*(radius*radius*radius);
        }
    }

    public static class Degrees
    {
        public static float Sin(float value)
        {
            return Mathf.Sin(value*Mathf.Deg2Rad);
        }

        public static float Cos(float value)
        {
            return Mathf.Cos(value * Mathf.Deg2Rad);
        }

        public static float Acos(float value)
        {
            return Mathf.Acos(value * Mathf.Deg2Rad);
        }

        public static float Asin(float value)
        {
            return Mathf.Asin(value * Mathf.Deg2Rad);
        }

        public static float Atan(float value)
        {
            return Mathf.Atan(value * Mathf.Deg2Rad);
        }

        public static float Tan(float value)
        {
            return Mathf.Tan(value * Mathf.Deg2Rad);
        }
    }

    public static float WedgeProduct(Vector2 lhs, Vector2 rhs)
    {
        return lhs.x*rhs.y - lhs.y*rhs.x;
    }

    public static float TripleScalarProduct(Vector3 a, Vector3 b, Vector3 c)
    {
        return Vector3.Dot(a, Vector3.Cross(b, c));
    }

    public static Vector3 TripleVectorProduct(Vector3 a, Vector3 b, Vector3 c)
    {
        return Vector3.Cross(a, Vector3.Cross(b, c));
    }

    public static Vector3 CrossProduct(Vector3 lhs, Vector3 rhs)
    {
        return Vector3.Cross(lhs, rhs);
    }

    public static float DotProduct(Vector2 lhs, Vector3 rhs)
    {
        return lhs.x*rhs.x + lhs.y*rhs.y;
    }

    public static class Intersect
    {
        //Отрезки 2D
        public static bool Segments(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2)
        {
            var dirA = a2 - a1;
            var dirB = b2 - b1;
            var dir1 = b1 - a1;
            var dirX1 = a2 - b1;
            var dirX2 = b2 - a1;
            var f1 = WedgeProduct(dirB, -dir1);
            var f2 = WedgeProduct(dirB, dirX1);
            var f3 = WedgeProduct(dirA, dir1);
            var f4 = WedgeProduct(dirA, dirX2);
            var result = (f1*f2 < 0) && (f3*f4 < 0);
            return result;
        }

        //Отрезки 3D
        public static bool Segments(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result)
        {
            result = new Vector3();

            Vector3 intersect;
            float t;
            if (Straight(a1, a2, b1, b2, out intersect, out t))
            {
                result = intersect;
                return t >= 0 && t <= 1;
            }
            return false;
        }

        public static bool Segments(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
        {
            Vector3 intersect;
            float t;
            if (Straight(a1, a2, b1, b2, out intersect, out t))
                return t >= 0 && t <= 1;
            return false;
        }

        public static Vector3? SegmentsNullable(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
        {
            Vector3 intersect;
            float t;
            if (Straight(a1, a2, b1, b2, out intersect, out t))
                return t >= 0 && t <= 1 ? (Vector3?) intersect : null;
            return null;
        }

        public static bool Straight(Vector2 a1, Vector2 a2, Vector2 b1, Vector2 b2)
        {
            var a = a2 - a1;
            var b = b2 - b1;
            return WedgeProduct(a, b).EqualsApprox(0f);
        }

        //Прямая 3D
        public static Vector3? StraightNullable(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
        {
            Vector3 intersect;
            float t;
            return Straight(a1, a2, b1, b2, out intersect, out t) ? (Vector3?) intersect : null;
        }

        public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
        {
            Vector3 intersect;
            float t;
            return Straight(a1, a2, b1, b2, out intersect, out t);
        }

        public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result)
        {
            result = new Vector3();
            Vector3 intersect;
            float t;
            if (Straight(a1, a2, b1, b2, out intersect, out t))
            {
                result = intersect;
                return true;
            }
            return false;
        }

        public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2, out Vector3 result, out float t)
        {
            var aDir = (a2 - a1).normalized;
            var bDir = (b2 - b1).normalized;
        
            result = new Vector3();
            t = -1;

            for (int xIndex = 0; xIndex < 3; xIndex++)
            {
                var yIndex = (xIndex + 1)%3;
                var zIndex = (xIndex + 2)%3;
                var n1 = new Vector2(aDir[xIndex], aDir[yIndex]);
                var n2 = -new Vector2(bDir[xIndex], bDir[yIndex]);
                var n3 = new Vector2(
                    b1[xIndex] - a1[xIndex],
                    b1[yIndex] - a1[yIndex]
                    );
                var det = n1.x * n2.y - n2.x * n1.y;
                if (Mathf.Abs(det) >= Mathf.Epsilon) // if det != 0
                {
                    var d1 = n3.x * n2.y - n2.x * n3.y;
                    var d2 = n1.x * n3.y - n1.y * n3.x;
                    var t1 = d1 / det;
                    var t2 = d2 / det;
                    var temp1 = a1[zIndex] + aDir[zIndex] * t1;
                    var temp2 = b1[zIndex] + bDir[zIndex] * t2;
                    if (Mathf.Abs(temp1 - temp2) < Mathf.Epsilon)
                    {
                        result = a1 + aDir*t1;
                        t = t1;
                        return true; // if temp1 = temp2
                    }
                    return false;
                }
            }
            return false;
        }
    }

    public static class Contains
    {
        public static bool Rectangle(Rect rect, Vector2 point)
        {
            return rect.Contains(point);
        }

        public static bool Segment(Vector2 a1, Vector2 a2, Vector2 point)
        {
            var v1 = a2 - a1;
            var v2 = point - a1;
            return WedgeProduct(v1, v2).EqualsApprox(0f) && Vector2.Dot(a1 - point, a2 - point) <= 0;
        }

        public static bool Straight(Vector2 a1, Vector2 a2, Vector2 point)
        {
            var v1 = (a2 - a1);
            var v2 = (point - a1);
            var diff = WedgeProduct(v1, v2);
            return diff.EqualsApprox(0f);
        }

        public static bool RayFromPoints(Vector2 aStart, Vector2 aFinish, Vector2 point)
        {
            return RayFromDir(aStart, (aFinish - aStart).normalized, point);
        }

        public static bool RayFromDir(Vector2 origin, Vector2 dir, Vector2 point)
        {
            var v1 = dir;
            var v2 = (point - origin);
            return WedgeProduct(v1, v2).EqualsApprox(0f) && Vector2.Dot(v1, v2) >= 0;
        }
    }

    /// <summary>
    /// Указывает, является ли угол выпуклым (по часовой стрелке)
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <param name="c"></param>
    /// <returns></returns>
    public static bool IsConvex(Vector2 a, Vector2 b, Vector2 c)
    {
        var AB = -(a - b);
        var BC = (c - b);
        var diff = WedgeProduct(AB, BC);
        return diff <= 0;
    }

    /// <summary>
    /// Указывает, является ли угол выпуклым (по часовой стрелке)
    /// </summary>
    /// <param name="a"></param>
    /// <param name="b"></param>
    /// <param name="c"></param>
    /// <returns></returns>
    public static bool IsConvex(Vector3 a, Vector3 b, Vector3 c)
    {
        var AB = -(a - b);
        var BC = (c - b);
        var dAB = Vector3.ProjectOnPlane(AB, new Vector3(0, 0, 1));
        var dBC = Vector3.ProjectOnPlane(BC, new Vector3(0, 0, 1));
        return IsConvex((Vector2)dAB, Vector2.zero, (Vector2)dBC);
    }

    public static Vector3 GetNormal(Vector3 a, Vector3 b, Vector3 c)
    {
        return Vector3.Normalize(Vector3.Cross(b - a, c - a));
    }

    /// <summary>
    /// Возвращает длины между двумя точками.
    /// Если точек больше двух, то возвращается так же длина между первой и последней точкой.
    /// Минимум 2 точки.
    /// </summary>
    public static float[] Longitudes(params Vector3[] points)
    {
        if (points.Length < 2)
            return new float[0];
        var count = points.Length != 2 ? points.Length : (points.Length - 1);
        var longitudes = new float[count];
        for (int i = 0; i < count; i++)
        {
            longitudes[i] = Vector3.Distance(points[i], points[(i + 1) % points.Length]);
        }
        return longitudes;
    }

    /// <summary>
    /// Возвращает длины между двумя точками.
    /// Если точек больше двух, то возвращается так же длина между первой и последней точкой.
    /// Минимум 2 точки.
    /// </summary>
    public static float[] Longitudes(params Vector2[] points)
    {
        if (points.Length < 2)
            return new float[0];
        var count = points.Length != 2 ? points.Length : (points.Length - 1);
        var longitudes = new float[count];
        for (int i = 0; i < count; i++)
        {
            longitudes[i] = Vector2.Distance(points[i], points[(i + 1) % points.Length]);
        }
        return longitudes;
    }
}

Много всякой херни, но вкратце по основному:
MinIndex/MaxIndex - возвращают индекс наименьшего/наибольшего элемента в массиве. Могут еще на доп условие проверить
Функции округления в большую/меньшую/ближайшую сторону - это тупо было скопировано из библиотеки Mathf под другими именами. Так лично мне удобней.
Функции округления для векторов - ну а почему бы и нет.
vectorScale - тупо заготовленный единичный вектор для размера. Не нашел нигде.
GetNormal для числа - нормализация числа, тобиш возврат единичного отрезка. Бывает необходимо.
Разные Product'ы для векторов - тут парочка старых добрых скалярного/векторного произведения + косое произведение + тройное векторное + тройное скалярное

В подклассе Area формулы чтобы посчитать площадь фигуры
В подклассе Perimeter формулы чтобы посчитать периметр фигуры
В подклассе Volume формулы чтобы посчитать объем фигуры
В подклассе Intersect формулы чтобы посчитать пересекаются ли фигуры
В подклассе Contains формулы чтобы посчитать содержит ли фигура точку
IsConvex - проверяет выпуклый ли угол по часовой стрелке
Longitudes - возвращает массив длин по указанным точкам

Ну и собственно - к чему я пишу. Я вообще по правде туп по части математики.
Потому хочу тут услышать ваши дополнения и быстрые алгоритмы чтобы что-то посчитать.
Меня очень напрягают функции Longitudes, IsConvex для Vector3, Intersect.Straight для Vector3.
Хотелось бы знать, если у вас есть лучшие решения для этих функций.
И еще в рунете не нашел никакой инфы "для чайников" по части вычислений с тройным скалярным произведением, как я понимаю решения через них самые быстрые. Если есть знатоки - пишите формулы, расскажите хоть-что нибудь об этом.



  • 1
  • 2 (Текущая страница)

Hellfim, разумно
Вот так сделал

       private static bool StraightIfNull(Vector3 a, Vector3 b)
        {
            a = a.normalized;
            b = b.normalized;
            return !(a.Equals(b) || a.Equals(-b));
        }

        public static bool Straight(Vector3 a, Vector3 b)
        {
            if (b.x == 0f || b.y == 0f || b.z == 0f)
                return StraightIfNull(a, b);
            var c = new Vector3(a.x / b.x, a.y / b.y, a.z / b.z);
            return !(c.x.EqualsApprox(c.y) && c.y.EqualsApprox(c.z));
        }

        public static bool Straight(Vector3 a1, Vector3 a2, Vector3 b1, Vector3 b2)
        {
            var a = (a2 - a1);
            var b = (b2 - b1);
            return Straight(a, b);
        }

Норм?

Extravert, да норм-то норм.
Просто странно. Если ты занялся оптимизацией, то зачем тогда StraightIfNull?

public static bool Straight(Vector3 a, Vector3 b)
{
	float k1=0, k2=0;

	if (b.x==0f)
	{
		if (a.x!=0) return false;
	}
	else k1=a.x/b.x;

	if (b.y==0f)
	{
		if (a.y!=0) return false;
	}
	else k2=a.y/b.y;

	//Если первые 2 коэффицента нулевые, значит вектора заданы строго по оси z, а значит они лежат на одной прямой.
	if ((k1==0f)&&(k2==0f)) return true;
	
	//Если первые 2 коэффицента не равны нулю и не равны между собой, то это разные векторы.
	if ((k1!=0f)&&(k2!=0f))
	{
		if (!k1.EqualApprox(k2)) return false;
	}
	//Если k2=0, то нам это не важно, мы перезапишем в него другое значение всё равно
	else if (k1==0f) k1=k2;

	if (b.z==0f)
	{
		if (a.z!=0) return false;
	}
	else k2=a.z/b.z;

	//В общем, векторы заданы вдоль одной оси, значит они на одной прямой.
	if (k2==0f) return true;

	return k1.EqualsApprox(k2));
}

При таком раскладе можно ещё и на одной переменной сэкономить, но это уже лишнее, имхо.

Вот есть у тебя четыре вектора, задающие две прямые: a, b, r1, r2.
первая прямая: r=r1+a*t
вторая прямая: r=r2+b*t
t - параметр, в случае прямой пробегает всю числовую ось, в случае отрезка - отрезок.

Тогда условие пересечения этих двух прямых: (a,b)!=0 and ( r1-r2, a, b )==0 (с какой-то точностью epsilon).
Где ( a, b, c ) - смешанное произведение, (a,b) - скалярное.
Будет сделано 9 умножений, 3 вычитания и 3 сложения для смешанного произведения; и ещё 3 сложения и 3 умножения для скалярного. Если вычисления ленивые(хз как C#), то именно в таком порядке проверки.

Но давайте поглядим на это с другой стороны.
Пусть у нас есть две прямые, лежащие "почти" в одной плоскости с точностью epsilon, и для них выполнено, что (a,b)!=0, т.е. они не параллельные. Тогда они пересекаются.
А вот и не факт. Если они лежат в двух плоскостях, лишь чуть-чуть наклонённых друг относительно друга, и ещё они разнесены( |r1-r2| велико ), то они на дальних расстояниях вообще будут далеко одна от другой. А мы их считаем пересекшимися, потому что наш метод работает только с какой-то точностью epsilon и может не почувствовать маленький угол, дающий большое расхождение на дальних дистанциях.

Что делать? А хз, мб и проверять в цикле. Или хитрить и пилить иной метод.

Так, стоп, нужно только в 2D? Тогда зря я это написал, тогда это в гугл...

Mihahail, наоборот 3D желательно. По 2D море инфы

Ну тогда можно попробовать мой алгоритм, точность выбрать что-то типа 1e-6
Только там ещё если r1-r2 ~ 0, то точка пересечения r=r1=r2

Ещё можно взять отсюда: http://mathportal.net/index.php/analiticheskaya-geometriya/ra...
Т.е. через расстояние между скрещивающимися прямыми, только там надо их проверить на параллельность сначала, а то на ноль поделить можно.

  • 1
  • 2 (Текущая страница)
Справка