Добавлен , опубликован
Моя имплементация векторов (2D и 3D) с полным набором инструментария для работы с ними.

Исходники в тексте:
Vec2
struct Vec2 {
    public float x, y;

    public Vec2 setVal(float x, float y) {
        this.x = x;
        this.y = y;
        return this;
    }

    public Vec2 clear() {
        return this.setVal(0.0, 0.0);
    }

    // Constructors
    public static Vec2 create() {
        return Vec2.allocate().setVal(0.0, 0.0);
    }

    public static Vec2 createAt(float x, float y) {
        return Vec2.allocate().setVal(x, y);
    }

    public static Vec2 createRandom() {
        return Vec2.allocate().setVal(GetRandomReal(-1.0, 1.0), GetRandomReal(-1.0, 1.0));
    }

    // Transitional behavior
    public Vec2 clone() {
        return Vec2.allocate().setVal(this.x, this.y);
    }

    public Vec2 copy(Vec2 another) {
        return this.setVal(another.x, another.y);
    }

    // Math
    public Vec2 add(Vec2 another) {
        return this.setVal(this.x + another.x, this.y + another.y);
    }

    public Vec2 sub(Vec2 another) {
        return this.setVal(this.x - another.x, this.y - another.y);
    }

    public Vec2 scale(float number) {
        return this.setVal(this.x*number, this.y*number);
    }

    public Vec2 div(float number) {
        return this.scale(1.0/number);
    }

    public float dot(Vec2 another) {
        return this.x*another.x + this.y*another.y;
    }

    public float lengthSqr() {
        return this.x*this.x + this.y*this.y;
    }

    public float length() {
        return SquareRoot(this.x*this.x + this.y*this.y);
    }

    public float distToSqr(Vec2 another) {
        return (this.x - another.x)*(this.x - another.x) + (this.y - another.y)*(this.y - another.y);
    }

    public float distTo(Vec2 another) {
        return SquareRoot(this.distToSqr(another));
    }

    public float angle(Vec2 another) {
        return Acos(this.dot(another)/this.length()*another.length());  // radians
    }

    public Vec2 normalize() {
        debug if (this.length == 0.0) { BJDebugMsg("attempt to normalize vector with zero length"); return this; }
        return this.scale(1.0/this.length());
    }

    // Misc.
    public Vec2 reflect(Vec2 normal) {
        Vec2 temp = normal.clone().scale(2.0*this.dot(normal));
        this.sub(temp);
        temp.destroy();
        return this;
    }
}
Vec3
struct Vec3 {
    public float x, y, z;

    public Vec3 setVal(float x, float y, float z) {
        this.x = x;
        this.y = y;
        this.z = z;
        return this;
    }

    public Vec3 clear() {
        return this.setVal(0.0, 0.0, 0.0);
    }

    // Constructors
    public static Vec3 create() {
        return Vec3.allocate().setVal(0.0, 0.0, 0.0);
    }

    public static Vec3 createAt(float x, float y, float z) {
        return Vec3.allocate().setVal(x, y, z);
    }

    public static Vec3 createRandom() {
        return Vec3.allocate().setVal(GetRandomReal(-1.0, 1.0), GetRandomReal(-1.0, 1.0), GetRandomReal(-1.0, 1.0));
    }

    // Transitional behavior
    public Vec3 clone() {
        return Vec3.allocate().setVal(this.x, this.y, this.z);
    }

    public Vec3 copy(Vec3 another) {
        return this.setVal(another.x, another.y, another.z);
    }

    // Math
    public Vec3 add(Vec3 another) {
        return this.setVal(this.x + another.x, this.y + another.y, this.z + another.z);
    }

    public Vec3 sub(Vec3 another) {
        return this.setVal(this.x - another.x, this.y - another.y, this.z - another.z);
    }

    public Vec3 scale(float number) {
        return this.setVal(this.x*number, this.y*number, this.z*number);
    }

    public Vec3 div(float number) {
        return this.scale(1.0/number);
    }

    public float dot(Vec3 another) {
        return this.x*another.x + this.y*another.y + this.z*another.z;
    }

    public float lengthSqr() {
        return this.x*this.x + this.y*this.y + this.z*this.z;
    }

    public float length() {
        return SquareRoot(this.x*this.x + this.y*this.y + this.z*this.z);
    }

    public float distToSqr(Vec3 another) {
        return (this.x - another.x)*(this.x - another.x) + (this.y - another.y)*(this.y - another.y) + (this.z - another.z)*(this.z - another.z);
    }

    public float distTo(Vec3 another) {
        return SquareRoot(this.distToSqr(another));
    }

    public float angle(Vec3 another) {
        return Acos(this.dot(another)/this.length()*another.length());
    }

    public Vec3 normalize() {
        debug if (this.length == 0.0) { BJDebugMsg("attempt to normalize vector with zero length"); return this; }
        return this.scale(1.0/this.length());
    }

    public static Vec3 cross(Vec3 edge1, Vec3 edge2) {
        return Vec3.createAt(edge1.y*edge2.z - edge1.z*edge2.y, edge1.z*edge2.x - edge1.x*edge2.z, edge1.x*edge2.y - edge1.y*edge2.x);
    }

    // Misc.
    public Vec3 reflect(Vec3 normal) {
        Vec3 temp = normal.clone().scale(2.0*this.dot(normal));
        this.sub(temp);
        temp.destroy();
        return this;
    }

    public static Vec3 triangleNormal(Vec3 a, Vec3 b, Vec3 c) {
        Vec3 edge1 = b.clone().sub(a);
        Vec3 edge2 = c.clone().sub(a);
        Vec3 result = Vec3.cross(edge1, edge2).normalize();
        edge1.destroy();
        edge2.destroy();
        return result;
    }
}
`
ОЖИДАНИЕ РЕКЛАМЫ...
1
29
6 лет назад
1
PrincePhoenix, почему частично?)
Как способ отточить свой скилл в векторах - да, стоит хоть раз в жизни написать свой солвер.
Как солвер для других - тысячу и один раз уже все было сделано до нас, со статьями причем.
0
30
6 лет назад
0
Msey, конкретно здесь самая визуально приятная реализация, на мой взгляд. Вон выше кидали «тоже самое» из DGUI, жесть же.

почему частично?)
Потому что я не бородатый!
Ну и ещё потому что векторы всё-таки полезная тема и много где нужная.
2
17
6 лет назад
2
Я бы предложил переименовать конструктор
public static Vec3 createAt(float x, float y, float z)
в
public static Vec3 create(float x, float y, float z)
А в свою очередь обычный
public static Vec3 create() 
в
public static Vec3 createZero() 
И добавить метод
    public string toString() {
        return "Vec3[" + R2S(x) + ", " + R2S(y) + ", "  + R2S(z) + "]";
    }
Аналогично для Vec2
0
30
6 лет назад
Отредактирован Clamp
0
GetLocalPlayer, хотел сохранить конструктор create() без параметров, чтобы поведение класса было максимально предсказуемым. Про toString идея неплохая, и я думал её реализовать, но потом понял, что не вижу ни одного юзкейса, где это было бы нужно, даже для дебага. Тоже самое про equals(Vec3), кстати.
0
26
6 лет назад
0
abidin:
Опять один бородатый программист написал никому не нужную фигню, чтобы обсудить это с двумя другими бородатыми программистами, которые занимаются той же ахинеей.
Такие темы могут быть интересны для общей информации. Например:
ScorpioT1000:
(локалки быстрее глобалок и быстрее обращений к массиву)
0
28
6 лет назад
Отредактирован Феникс
0
8gabriel8, Это всё опять же заморочки кодеров, для обычного картостроителя эта инфа настолько мизерна, что даже не знаю.

Но! Такие треды, в первую очередь, помогают тем, кто хочет развиться дальше варкрафта и уйти в геймдев.
0
4
6 лет назад
0
PrincePhoenix, лучше тогда в статью про геймдев закинуть в целях обучения. Там он был бы чуть
полезнее, если бы были ещё и картинки. А так данные методы написаны для лентяев, которые не хотят ничего учить, а хотят дергать за рычаги и получать результат.
1
17
6 лет назад
1
не вижу ни одного юзкейса
Такие темы могут быть интересны для общей информации.
Для практического применения такие библиотеки должны дополнять стандартный функционал редактора. Wurst, например, в стандартной библиотеке тоже содержит типы vec2 и vec3, но в добавок он расширяет стандартные типы для их использования. Например, все функции устанавливающие координаты тем или иным объектам принимают в качестве параметров именно vec2 и vec3, в чем и раскрывается их мощь. А для старого vJass, это да, это по большому счету, простите, пердёж в подушку.
PrincePhoenix:
Но! Такие треды, в первую очередь, помогают тем, кто хочет развиться дальше варкрафта и уйти в геймдев.
Одно другому не мешает. WC3 как конструктор лего, больше развлечение чем работа. Жвачка для мозгов, может быть.
0
29
6 лет назад
0
В вжассе методы add, sub, scale, div разве нельзя представить в виде перегрузки операторов?
0
37
6 лет назад
0
abidin, какие рычаги?) либа как либа
0
30
6 лет назад
0
Для практического применения такие библиотеки должны дополнять стандартный функционал редактора.
Практически применял эту библиотеку, что я делал не так?
0
29
6 лет назад
0
В вжассе методы add, sub, scale, div разве нельзя представить в виде перегрузки операторов?
Насколько я помню в вжассе перегрузка операторов сделана только для []
0
30
6 лет назад
0
Doc, ещё для =, >, < и ==.
0
28
6 лет назад
Отредактирован PT153
0
(локалки быстрее глобалок и быстрее обращений к массиву)
Драколич говорил, что время обращения к глобалкам и локалкам одинаковое. А обращение к ячейке массива, очевидно, будет дольше в обоих случаях.
Драколич говорил, что время обращения к глобалкам и локалкам одинаковое.
Да и сам я так считаю, не вижу причин для большего времени обращения к глобальным переменным. Ведь все переменные будут располагаться в одной памяти, а значит, формат адресации будет одинаков.
0
26
6 лет назад
0
PT153, ну, наверное, у ScorpioT1000 есть свои аргументы, раз он так утверждает.
2
30
6 лет назад
2
Локалки выделяются в регистрах метода же, а глобалки в общей куче.
0
37
6 лет назад
0
Тоад и диод проводили исследования, причем скорость еще зависит от длины идентификатора (имени)
0
28
6 лет назад
Отредактирован PT153
0
Тоад и диод
Ой, а кто это? Было бы неплохо ссылку на само исследование сюда или мне в ЛС, думаю, мне будет интересно почитать.
2
37
6 лет назад
Отредактирован ScorpioT1000
2
PT153, перепутал, это Адольф, читать отсюда xgm.guru/forum/showthread.php?p=467961#post467961
конкретно пост xgm.guru/forum/showpost.php?p=468024&postcount=26
0
17
6 лет назад
0
Практически применял эту библиотеку, что я делал не так?
Подразумевалось повседневное использование, скажем, вместо глобалок X/Y для координат юнита. Сейчас это не актуально из-за необходимости вызывать конструктор/деструктор и невозможности передать стандартным функциям вектор напрямую. Писанины становится слишком много ради простой пары координат.
Clamp:
Doc, ещё для =, >, < и ==.
Только для < и ==
> и != генерируются автоматически на основе их обратных эквивалентов.
0
30
6 лет назад
Отредактирован Clamp
0
"> и != генерируются автоматически на основе их обратных эквивалентов.
А что, они при этом не перегружаются? К чему это уточнение?

Подразумевалось повседневное использование, скажем, вместо глобалок X/Y для координат юнита.
Юзайте Location, оно как раз для этого было введено. Векторы нужны для описания движения (хотя, надо сказать, что все юниты, которых я передвигал, двигались вдоль векторов). Вообще могу поискать свою демку физики, там всё ну очень просто, и никаких проблем с использованием этих векторов не было.

Никто здесь не делал претензий на то, что пишет свой язык, (вурст говно кстати в плане удобства синтаксиса).
0
29
6 лет назад
Отредактирован Doc
0
К чему это уточнение?
К тому что разные реализации < и > написать нельзя.
Юзайте Location, оно как раз для этого было введено
Глупый вывод, локейшн это хендл, не все нативки его принимают, занимает время на создание.
В вурсте с синтаксисом все замечательно, не знаю, откуда такие новости. Питон считается одним из топовых языков в плане синтаксиса
и никаких проблем с использованием этих векторов не было.
С тем же успехом можно сказать, что у Жона в ДГУИ тоже никаких проблем не было, зачем эта либа тогда?
2
17
6 лет назад
Отредактирован GetLocalPlayer
2
А что, они при этом не перегружаются? К чему это уточнение?
Doc, уже ответил, контроля нет.
Clamp:
Юзайте Location, оно как раз для этого было введено.
Что не отличается от неудобств использования вектора. Как уже сказал Doc, не все функции принимают Location. Более того, использовать его нисколько не удобно, из-за необходимости вызова сторонней функции для получения хранящихся в нём данных и хуже всего, это хэндл, который надо уничтожать (подобно векторам) и обнулять.
Clamp:
Никто здесь не делал претензий на то, что пишет свой язык, (вурст говно кстати в плане удобства синтаксиса).
Это вкусавщина. Тебе удобно упираться в фигурные скобки и писанину function/takes/returns/endfunction, а кому-то нужна краткость и объективность.
Что отрицать не получится, что Wurst - единственный полноценный компилятор не брошенный разработчиком, с самым широким спектром возможностей супротив его предшественникам.
2
37
6 лет назад
Отредактирован ScorpioT1000
2
У вурст есть одна проблема: это неизвестный ЯП, который никоим боком, кроме либы, не относится ни к warcraft 3, ни к чему угодно вне warcraft 3
0
17
6 лет назад
Отредактирован GetLocalPlayer
0
То же можно сказать о cJass, но это никого не смущает.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.