JOML-CI / JOML

A Java math library for OpenGL rendering calculations
MIT License
715 stars 102 forks source link

A simpler way to create a Vector2d from a Vector3d #336

Closed xupwup closed 1 year ago

xupwup commented 1 year ago

I'd like to have an easier way to get a lower dimension vector from a higher dimension vector. Usually from 3 dimensions to two, but from 4 to 3 too.

Currently, the only way to do this is the following:

Vector3d a = new Vector3d(1, 2, 3);
Vector2d b = new Vector2d(a.x, a.y);

I'd like to have something like in GLSL:

Vector2d b = a.xy(); // the one you need 9 times out of 10
Vector2d c = a.xx();
Vector2d d = a.zy();

This mainly helps when the vector3d is obtained via a long function chain:

Vector3d a = getDirectionOfSomethingDifficult().cross(getOtherThing());
Vector2d b = new Vector2d(a.x, a.y);
double lengthIn2d = b.length();
httpdigest commented 1 year ago

We could do this, but given that JOML wants to stay allocation-free, we would have to make it like this:

Vector2d b = a.xy(new Vector2d());

(of course this new Vector2d() can be another variable declared and allocated somewhere else)

xupwup commented 1 year ago

That would be a great improvement. Alternatively, maybe you could return it as a view on the data? (through Vector2dc) EDIT: never mind, a view also requires you to allocate something.

Or just make it explicit in the function name that this function allocates something.

httpdigest commented 1 year ago

EDIT: never mind, a view also requires you to allocate something.

Initially, I thought that you meant that every Vector3d should also be a Vector2dc. :) But that would invalidate Liskov Substitution Principle (e.g. changing the z component on the Vector3d would result in a different result for Vector2dc's length().

xupwup commented 1 year ago

No, my idea was just bad :D But Vector3d.xy(new Vector2d()) would be great. Could you also make Vector3d.xy(new Vector2f()) work? And Vector3f.xy(new Vector2d()) and Vector3f.xy(new Vector2f())?

httpdigest commented 1 year ago

But would adding these "swizzle" methods really justify bloating the classes/jar up? I mean, theoretically, people could then ask for all sorts of other 4d to 3d swizzles, etc, including vector4.xxx(vector3d), etc. I am not thaaat convinced that writing Vector2d xy = new Vector2d(xyz.x(), xyz.y()) is thaaat much of a burden.

xupwup commented 1 year ago

No, I think all the swizzles don't add that much value. But truncating a 3d vector to a 2d vector is quite common in our codebase.

Another suggestion: why not add it to Vector2d's constructor? Like this:


   public Vector2d(Vector3d v) {
      x = v.x;
      y = v.y;
   }

Also, on a separate note, could you add a double to float constructor to Vector2f (and 3f and 4f)?


    public Vector2f(Vector2dc v) {
        x = (float) v.x();
        y = (float) v.y();
    }