I'm working on a three_js project, but it's the Flutter package three_js, not the JavaScript module three.js. Recently I've been converting some JavaScript code to Flutter using three_js, and I can't figure out how to set a buffer geometry attribute. Here's the JavaScript:
const g = new THREE.BufferGeometry();
g.setAttribute(
'position',
new THREE.BufferAttribute(new Float32Array(this.branches.verts), 3),
);
g.setAttribute(
'normal',
new THREE.BufferAttribute(new Float32Array(this.branches.normals), 3),
);
g.setAttribute(
'uv',
new THREE.BufferAttribute(new Float32Array(this.branches.uvs), 2),
);
g.setIndex(
new THREE.BufferAttribute(new Uint16Array(this.branches.indices), 1),
);
The first thing that caught me by surprise was the order of function parameters, I looked at the source code and found this function syntax: BufferGeometry setAttribute(Attribute type, dynamic attribute)
, which switches the parameters as compared to the JavaScript version. Now of course, I should expect some changes in code when comparing a port from one language to another, for multiple reasons, so this wasn't too weird. Quick fix, all I have to do is switch the order of my parameters, right? Nope. I switched the order, then realized I had a bigger problem.
When I tried to initialize the class Attribute, this is what VS Code said to me: "Generative enum constructors can only be used as targets of redirection." I'm not quite sure what that means, but I thought I might be able to get away with just using BufferAttribute and then type casting...but BufferAttribute is apparently an abstract class, so I went with Float32BufferAttribute
(and Uint16BufferAttribute
), and then type casted, like this:
g.setAttribute(
three.Float32BufferAttribute(three.Float32Array.fromList(normals), 3) as three.Attribute,
'normal'
);
This made the errors go away, but it also didn't work, since it didn't apply correctly to the screen when I ran it.
At this point, I'm looking for someone who knows what all of this means, and what the correct syntax of the function is. Given that three_js
is a port from three.js, it's not as commonly known in the developer community, and therefore there aren't as many answers to my questions.
Note: I realize that copying directly from JavaScript isn't optimized or good practice, but please ignore it for the sake of the question being asked.
From the documentation, the order doesn't appear to have changed at all. You have simply misunderstood the purpose of the Attribute
type of the first parameter.
Here, Attribute
is an enum to replace the magic string that Three.JS uses (or union type if you're using the Typescript definitions). So instead of setAttribute('position', ...)
you would use setAttribute(Attribute.position, ...)
. You would then pass the corresponding BufferAttribute
object to the second dynamic parameter (which should really be better documented, but I guess they are depending on you consulting the Three.JS documentation and performing the necessary conversions yourself).
So the Dart version of:
g.setAttribute(
'position',
new THREE.BufferAttribute(new Float32Array(this.branches.verts), 3),
);
should be:
g.setAttribute(
Attribute.position,
three.Float32BufferAttribute(three.Float32Array.fromList(verts), 3),
);
// OR
g.setAttribute(
Attribute.position,
three.Float32BufferAttribute.fromList(verts, 3),
);
Alternatively, you could use setAttributeFromString
to get a more similar syntax to the JS version, but I wouldn't recommend that if at all possible.