I am working on a game. Because I don’t want to marry frameworks, I wrote an abstraction for the graphics engine and am now trying to shoehorn three.js into it.
I am working with gl-matrix for vector math (using vec3
, typed arrays), three.js has its own vector classes (using {x:number, y:number, z:number}
). My interface for a 3d object looks as follows:
interface Thing{
...
position:vec3
}
and my implementation looks like this:
class ThreeJsThing implements Thing{
...
set position(p:vec3){
this.mesh.position.set(p[0], p[1], p[2]) // [,,] -> {xyz}
}
get position(){
let p = this.mesh.position
return vec3.fromValues(p.x, p.y, p.z) // {xyz} -> [,,]
}
}
Now it’s all fun and games until someone tries to do:
let myThing = new ThreeJsThing()
myThing.position[1] = 5 // only changes a temporary copy that is returned by the getter
And with gl-matrix this is especially a problem because it uses output parameters for performance reasons, internally doing that array assignment above:
vec3.add(myThing.position, a, b)
I know how to work around this problem because I am (now) aware of it, but other contributors are probably also going to choke on this, especially since it fails silently. Just from a clean code point of view, I can’t really pinpoint where I used anti-patterns or bad design or something. I find ThreeJsThing
to be as faithful to the interface as possible. I have some suspicions:
- maybe this is just a general problem with set and get and they should be avoided?
- maybe set and get should not do copies and only accept/return and internally work with references of the same type?
- output parameters are frowned upon (but then
myThing.position[1] = 5
is still a problem)
Any advice appreciated.