Define 3D math structures in Haxe using Abstracts

122 views
Skip to first unread message

Remco Huijser

unread,
Feb 10, 2017, 5:15:42 AM2/10/17
to Haxe
Hi all,

I have been looking at using Abstracts for describing data structures like a Vector3 or Matrix in our code. All example deal with the case where an abstract can only be a single concrete type. Storing multiple values would mean storing them in an array.

abstract Vector3(Array<Float>)
{
inline public function new(x : Float = 0, y : Float = 0, z : Float = 0)
{
this = [x, y, z];
}
}

// This makes that this:
var vector = new Vector3();

// Is actually compiled to this:
var vector = [0, 0, 0]

I was wondering whether there is a way to define an Abstract with multiple concrete types.

// This makes that this:
var vector = new Vector3();

// Is actually compiled to this:
var vectorX = 0;
var vectorY = 0;
var vectorZ = 0;

There are of course a lot of complexities here:
  • What happens when passing a Vector3 to a function?
  • What happens when returning a Vector3 from a function?
  • What happens when you define an array of Vector3 values?
I do believe that this might have some benefits
  • Let garbage collection: you no longer need to create instances of the Vector3 class, you just pass around Float values
  • You might even be able to perform swizzles: use vector.xxx to get an instance of Vector3 with 3 times the x value.
  • The swizzle might actually be pretty cool for matrices as well: you could use matrix.position to get a Vector3 from position 41, 42 and 43 without actually creating a new Vector3 instance.
Regards,

Rem

Yoni Gueta

unread,
Feb 10, 2017, 6:14:14 AM2/10/17
to Haxe


although it still uses arrays as the underlying type, this is a good reference:

Gama11

unread,
Feb 10, 2017, 8:15:33 AM2/10/17
to Haxe
Regarding GC benefits: do you know about inline constructors?

Remco Huijser

unread,
Feb 14, 2017, 3:19:40 AM2/14/17
to Haxe
Inline constructors are indeed a thing of beauty: I will need to look into this some more. This would allow me to avoid creating copies inside functions where I need to do some manipulation math.

What I did notice is that the resulting code looks a bit weird in Haxe 3.4

Let's say we have this Vector3 class:

class Vector3 
{
public var X : Float;
public var Y : Float;
public var Z : Float;

public inline function new(x : Float, y : Float, z : Float)
{
this.X = x;
this.Y = y;
this.Z = z;
}

public inline function AddValue(value : Float)
{
this.X += value;
this.Y += value;
this.Z += value;
}
}

How if we would write this code:
static function TestVector(vector : Vector3)
{
var copy = new Vector3(vector.X, vector.Y, vector.Z);
copy.AddValue(10);
}

It gets compile to this. I find it rather strange that copy_Y and copy_Z are assigned later on. I wonder if this is slightly less performant or something in JS, but it does avoid creating an actual copy.

Main.TestVector = function(vector) {
var copy_Z;
var copy_Y;
var copy_X = vector.X;
copy_Y = vector.Y;
copy_Z = vector.Z;
copy_X += 10;
copy_Y += 10;
copy_Z += 10;
};

When enabling the -D analyzer-optimize flag you get this. I find this rather peculiar as one of the goals of the optimizer is to create more compact/less code, right?

Main.TestVector = function(vector) {
var copy_Z;
var copy_Y;
var copy_X;
var x = vector.X;
var y = vector.Y;
var z = vector.Z;
copy_X = x;
copy_Y = y;
copy_Z = z;
copy_X = x + 10;
copy_Y = y + 10;
copy_Z = z + 10;
};

Remco Huijser

unread,
Feb 14, 2017, 3:40:12 AM2/14/17
to Haxe
Thanks for the link! I do believe there is a significant performance impact of using arrays over objects.

I created a small test to confirm this here: http://jsben.ch/#/Ou8Ez
This test compares a vector as object to a vector as array and even a vector as float array
Reply all
Reply to author
Forward
0 new messages