Godot: More constructors for Vectors

Created on 18 Oct 2016  路  17Comments  路  Source: godotengine/godot

Currently, it is pretty long to make a Vector3 out of a Vector2:

Vector3(vec2.x, vec2.y, 0)

Same goes for vice-versa:

Vector2(vec3.x, vec3.y)

Now, imagine that the said Vector3/Vector2 has a very long name.. It would quickly become unmanageble, right? :smile:


That's why, I would like to propose (after a quick discussion with @karroffel and @reduz) a few utility constructors, similar to the shading language (which should be non-implicit, to minimize bugs):

func Vector3(Vector2 xy, float z = 0):
func Vector3(float x = 0, Vector2 yz):
func Vector2(Vector3 xy):

Now, the only few issues with this is that you can't:

  1. Make Vector3(v2.y, v2.x, 0), for example
  2. Make Vector2(v3.z, v3.x), which might need swizzling to work properly.

Anyway, what do you think of the proposed constructors? And also, do you think swizzling (v3.xz) is useful enough to include in GDScript?

archived discussion feature proposal gdscript

Most helpful comment

I think you're trying to solve a problem that doesn't exist. Most proposals made here are more convoluted than just a plain pos3d = Vector3(pos2d.x, 0, pos2d.y).

So I think https://github.com/godotengine/godot/issues/6861#issuecomment-254495968 was the best proposal, once removed the Vector2D weird swizzling (people will continue handling xz case manually - if it ever has a use case).

All 17 comments

I would expect something like this:

var pos3d = Vector3(v2, 0) # Same as Vector3(v.x, v.y, 0), and the 0 can be omitted
var pos3d = Vector3(0, v2) # Same as Vector3(0, v.x, v.y)
var pos3d = v2.xz # Same as Vector3(v.x, 0, v.y), although I would still prefer writing this

var pos2d = v3.xy # Same as Vector2(v.x, v.y)
var pos2d = v3.xz # Same as Vector2(v.x, v.z)

I didn't played enough with 3D to know if I really need these in Godot, but I know I also need component indexing (like, pos[0], pos[1] instead of pos.x and pos.y). But these appear to be available already, which is good :)

@Zylann I agree fully except for the v2.xz, which is a bit odd (v2 doesn't have a z member).

What about using a SKIP_AXIS_X/Y/Z parameter like:

func Vector2(Vector3, SKIP_AXIS_X)
func Vector2(Vector3, SKIP_AXIS_Y)
func Vector2(Vector3, SKIP_AXIS_Z)

SKIP_AXIS_Z will be the default value.

Same goes for Vector3 from Vector2.

func Vector3(Vector2, SKIP_AXIS_X/Y/Z)

Example 2d to 3d:

var vec2d = Vector2(20,30)
var vec3d = Vector3(vec2d, SKIP_AXIS_Y)
# Vec3d will be (20,0,30)

Example 3d to 2d:

var vec3d = Vector3(30,40,50)
var vec2d = Vector2(vec3d, SKIP_AXIS_Y)
# Vec2d will be (30,50)

Adding a FLIP_ORDER / KEEP_ORDER parameter may help in some situations

func Vector3(Vector2, SKIP_AXIS_X/Y/Z, FLIP_ORDER)

Example 2d to 3d with FLIP_ORDER:

var vec2d = Vector2(20,30)
var vec3d = Vector3(vec2d, SKIP_AXIS_Y, FLIP_ORDER)
# Vec3d will be (30,0,20)

Does these make sense?

Although it solves the oddity of var pos3d = v2.xz, I don't really like it either. Maybe something like pos3d = Vector3.xz(v2)? (named constructor, often useful but not used enough in Godot :p)

Another Idea:

pos2D = Vector2(pos3D, TRANSLATE_TO_XY)
pos2D = Vector2(pos3D, TRANSLATE_TO_XZ)
pos2D = Vector2(pos3D, TRANSLATE_TO_YX)
pos2D = Vector2(pos3D, TRANSLATE_TO_YZ)
pos2D = Vector2(pos3D, TRANSLATE_TO_ZX)
pos2D = Vector2(pos3D, TRANSLATE_TO_ZY)

more constants but more verbose. :)

@Zylann But another constructor without overloading main one is better.

pos2D = Vector2.project_on_xy(pos3D)
pos2D = Vector2.project_on_xz(pos3D)
...
...

This is getting way too complicated for something that should be sugar for a trivial operation.

What if written other way around? Adding as setter not getter:

pos3d.xz = pos2D
pos3d.xz = Vector2D(a,b)

OR

pos3d.xz(pos2D)
pos3d = Vector3D().xz(pos2D)

Will this be simple and prevent missing axis oddity?

Edit: For 2D this may get complicated it seems. :(

I think you're trying to solve a problem that doesn't exist. Most proposals made here are more convoluted than just a plain pos3d = Vector3(pos2d.x, 0, pos2d.y).

So I think https://github.com/godotengine/godot/issues/6861#issuecomment-254495968 was the best proposal, once removed the Vector2D weird swizzling (people will continue handling xz case manually - if it ever has a use case).

The use case I would see for xz is that the 3D engine is Y-up, so converting between top-down 2D coordinates into 3D coordinates is something that will happen. But again I'm not experienced enough in the use of 3D in Godot so I can't back this up with facts :p
I would use the explicit method anyways.

I use XZ quite often in my 3d projects because of the "3D Y-up to top-down 2D" conversion as mentioned by @Zylann.

It is sometime more convenient to use 2D math even for 3D, and being able to quickly switch from Vector2 to Vector3 and vice-versa could be very handy.

I've been thinking about opening a feature request for "gdscript Vector2/3 swizzling" for months, but I thought this idea would not gather enough support.
In the end @bojidar-bg got a similar idea.

If #6866 is implemented, we _might_ somehow do this instead:

Vector3(xz = v2, y = 0)

@bojidar-bg not quite, it would imply that an xz argument exists in a two-parameter constructor with the correct semantic. Unless you do a constructor with (x, y, z, xy, yz, xz, yx, zy, zx, ...) :D Or named arguments would have to behave differently especially for this case.

Using a helper function would tackle this better:

static func vec3_xz(v2):
    return Vector3(v2.x, 0, v2.z)

I think this is still relevant in latest master 3ad9e47 ?

I'm not aware of any functionallity like this being added to vectors (as in https://github.com/godotengine/godot/issues/6861#issuecomment-254495968)

I was just about to create similar issue. Any progress on this?

For the xz stuff I've seen somewhere else the use of a "zero accessor", with the name "o". So you could do something like

vec2.xoy
# Same as
Vector3(vec2.x, 0.0, vec2.z)

I don't remember where I saw it.

Feature and improvement proposals for the Godot Engine are now being discussed and reviewed in a dedicated Godot Improvement Proposals (GIP) (godotengine/godot-proposals) issue tracker. The GIP tracker has a detailed issue template designed so that proposals include all the relevant information to start a productive discussion and help the community assess the validity of the proposal for the engine.

The main (godotengine/godot) tracker is now solely dedicated to bug reports and Pull Requests, enabling contributors to have a better focus on bug fixing work. Therefore, we are now closing all older feature proposals on the main issue tracker.

If you are interested in this feature proposal, please open a new proposal on the GIP tracker following the given issue template (after checking that it doesn't exist already). Be sure to reference this closed issue if it includes any relevant discussion (which you are also encouraged to summarize in the new proposal). Thanks in advance!

Was this page helpful?
0 / 5 - 0 ratings