Добавлен , опубликован
Моя имплементация векторов (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;
    }
}
`
ОЖИДАНИЕ РЕКЛАМЫ...

Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
38
PT153, лишняя память. Вектор - такой объект, который может создаваться миллионами единиц (в варкрафте нет).
30
Я бы вообще сделал вектор неизменяемым.
И пересоздавал каждый раз? Это ещё тяжелее может оказаться. Кроме того, длинна может вообще быть не нужна в системе, и будет храниться мёртвым грузом.

в варкрафте нет
Когда делал демку физики, доводил до 3к физических объектов, в пике нагрузки жило до 4к векторов, так что даже в варкрафте можно ощутимый импакт на потребление памяти увидеть.
38
Ну вон xcoll / xdestr вроде всегда хранит и передаёт 3 коорды, чтобы было ещё легче (локалки быстрее глобалок и быстрее обращений к массиву)
4
Опять один бородатый программист написал никому не нужную фигню, чтобы обсудить это с двумя другими бородатыми программистами, которые занимаются той же ахинеей.
29
abidin, это ты конечно зря сейчас сказал, хоть и частично правда.
29
PrincePhoenix, почему частично?)
Как способ отточить свой скилл в векторах - да, стоит хоть раз в жизни написать свой солвер.
Как солвер для других - тысячу и один раз уже все было сделано до нас, со статьями причем.
30
Msey, конкретно здесь самая визуально приятная реализация, на мой взгляд. Вон выше кидали «тоже самое» из DGUI, жесть же.

почему частично?)
Потому что я не бородатый!
Ну и ещё потому что векторы всё-таки полезная тема и много где нужная.
15
Я бы предложил переименовать конструктор
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
30
GetLocalPlayer, хотел сохранить конструктор create() без параметров, чтобы поведение класса было максимально предсказуемым. Про toString идея неплохая, и я думал её реализовать, но потом понял, что не вижу ни одного юзкейса, где это было бы нужно, даже для дебага. Тоже самое про equals(Vec3), кстати.
26
abidin:
Опять один бородатый программист написал никому не нужную фигню, чтобы обсудить это с двумя другими бородатыми программистами, которые занимаются той же ахинеей.
Такие темы могут быть интересны для общей информации. Например:
ScorpioT1000:
(локалки быстрее глобалок и быстрее обращений к массиву)
29
8gabriel8, Это всё опять же заморочки кодеров, для обычного картостроителя эта инфа настолько мизерна, что даже не знаю.

Но! Такие треды, в первую очередь, помогают тем, кто хочет развиться дальше варкрафта и уйти в геймдев.
Показан только небольшой набор комментариев вокруг указанного. Перейти к актуальным.
Чтобы оставить комментарий, пожалуйста, войдите на сайт.