Dreaman Dreaman

Mariya, законченный вариант реально классно выглядит! Молодец :)

Mariya Mariya

Всем привет!
Сегодня хочу показать законченный вариант домика Сырны.

alexprey alexprey

StarPlosion: Битва с пиратами за планету

Wings' might Wings' might

Всем привет)
Добавил на этой неделе начальное окно, новую валюту и достижения:

alexprey alexprey

shadeborn, может быть они нашли способ как обойти полноценный запуск этих сервисов при запуске игры? Если так, то почему бы и не использовать единый клиент?) В любом случае, чем дальше все идет, там это все больше становится похоже на эту шутку

...
shadeborn shadeborn

Это всё круто, но...зачем? Ок есть Стим. Хорошо, теперь еще и ЕГС есть. Благо, комп не зашкварен Оригином...но у людей и он стоит. И для работы игр внутри этих сервисов нужны, собсно, эти сервисы. Так поверх этих сервисов нужно накатить еще один...

Devion Devion

согласен, есть кейсы которые без них вообще не делаются, не знать или избегать их определенно неправильно

Так точно, либо любое изменение в объекте на стороне редактора.

alexprey alexprey

Devion, только рад за дополнение, Спасибо)

хм, а вот это интересно, не пробовал никогда такой кейс.

Devion Devion

лёш, ты же не против если я дополню? )

скриптаблы, для понимания могут храниться на уровне ассета и на уровне сцены.

Mariya Mariya

Всем привет!
Начали работу над мебелью в домик Сырны, и первым сделали чайный столик с чайным сервизом. А так же продолжаем работу над анимациями.

Wings' might Wings' might

Всем привет)
За неделю в игру было добавлено меню настроек, переделана старая локация, добавлены новые враги и повышена производительности

alexprey alexprey

А мне кажется это такой особый хитрый ход, хотя с другой стороны как разработчики успеют к этому подготовиться получше 🤔

Dreaman Dreaman

Всем привет!
Для проекта "Mental State" разработано новое устройство, которое уже полностью функционирует внутри игрового мира. Оно носит название "Репульсивер". Совместно с очередными большими воротами это устройство образует новую головоломку...

...
Mariya Mariya

Всем привет!
На этой неделе мы научили Сырну летать!

Tartal Tartal

alexprey, кастомизации - создание внешности персонажа? Я всегда любил это, но не думаю, что это будет к месту в мясном шутере)
EfimovMax, да, есть немного)

Tartal Tartal

Jusper, точно не помню, уже как полгода точно) Я вроде в Дискорде немного обсуждал эту тему. Пока немножко попробовал движок - мне очень нравится. Ну, в конце концов, он идеально подходит под жанры, с которыми я хочу работать...

alexprey alexprey

Первая тема крутая очень!

Логотип проекта 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 (Текущая страница)