ungerik / go3d

A performance oriented 2D/3D math package for Go
MIT License
303 stars 49 forks source link

vec3.Add() and similar should return a pointer #14

Closed alexozer closed 9 years ago

alexozer commented 9 years ago

The functions with names in the past tense that operate on more than one object (like vec3.Add()) should (imo) return a pointer to the result, not a normal object. This makes these functions consistent with their corresponding methods on the datatypes and makes it much easier to chain vector operations.

For example, let's say I have three points (vec3.T) and want to find the area of the triangle whose vertices are the points.

pt1 := vec3.T{0, 0, 0}
pt2 := vec3.T{3, 5, 1}
pt3 := vec3.T{6, 2, -1}

To calculate the area without modifying pt1, pt2, or pt3, I would have to do this:

v1 := vec.Sub(&pt2, &pt1)
v2 := vec.Sub(&pt3, &pt2)
areaVec := vec.Cross(&v1, &v2)
return areaVec.Length()

But if all functions that operate on vec3's return a pointer, it's simpler:

return vec.Cross(vec.Sub(&pt2, &pt1), vec.Sub(&pt3, &pt2)).Length()

I'm sure you came across this dilemma when designing go3d initially, but I'd like to at least hear your rationale for this design decision if nothing more.

ungerik commented 9 years ago

The reason is simple: performance! vec3.Add() would have to allocate a new object on the heap which is slow and also adds to garbage collection load. go3d is described as "A performance oriented 2D/3D math package for Go".

ungerik commented 9 years ago

Note that the package is designed for performance over usability where necessary. This is the reason why many arguments are passed by pointer reference instead of by value. Sticking either to passing and returning everything by value or by pointer would lead to a nicer API, but it would be slower as demonstrated in mat4/mat4_test.go

cd mat4
go test -bench=BenchmarkMulAddVec4_PassBy*