3

I am writing a component that needs to access and modify position, normal, and uv attributes on a model read into A-Frame as an asset. I can get close to accessing the data, but can't quite get there. Using:

document.querySelector('a-entity').object3D.children

seems to give me an array, but trying to access the elements gives me an object with empty children and empty geometry.

My guess is that I'm trying to access the data through the wrong door and while:

console.log(document.querySelector('a-entity').object3D.children);

shows me an array size=1 with a populated Object element

console.log(document.querySelector('a-entity').object3D.children[0]);

gives me the element with the empty geo, etc. What is the right mechanism or syntax to use to get at the data?

Scott Singer
  • 141
  • 1
  • 9

1 Answers1

4

There are two three.js classes you'll need to know about here: Geometry and BufferGeometry. The former already has properties for geometry.vertices and geometry.faces (see documentation there). Vertices are an array of THREE.Vertex3 objects, and easy to work with.

If you have a BufferGeometry, then instead you have geometry.attributes.position which is not an array of THREE.Vertex3, but instead contains a flat array of floats, like [x1, y1, z1, x2, y2, ...]. This is more efficient, but harder to modify manually.

If you have BufferGeometry but would rather work with Geometry, then you can convert either way:

var geometry = Geometry.fromBufferGeometry( mesh.geometry );
mesh.geometry =  BufferGeometry.fromGeometry( geometry );

An A-Frame specific note, usually you'll get a reference to the mesh by doing el.getObject3D('mesh'). For custom models that might be a nested group, in which case:

el.object3D.traverse(function(node) {
  if (node.geometry) { /* ... */ }
});

(three.js r84)

xxx
  • 1,153
  • 1
  • 11
  • 23
Don McCurdy
  • 10,975
  • 2
  • 37
  • 75
  • this.el.object3D.traverse(function(node) { if (node.geometry) { console.log(node.geometry); } }); prints the geometry object but there's no attribute data in it – Scott Singer Apr 12 '17 at 16:02
  • sorry about the lack of formatting in that comment. Basically when I try and access the data within the node.geometry is appears to be unpopulated. Is there a syntax for accessing it that I'm missing? – Scott Singer Apr 12 '17 at 16:19
  • your suggestion works on a entity but the same thing on an OBJ model gives: `TypeError: node.geometry.attributes.position is undefined` – Scott Singer Apr 12 '17 at 17:13
  • Are you sure have BufferGeometry? if `node.geometry.attributes` does not exist, it is not a BufferGeometry. If `node.geometry` does not exist, the node is not a mesh and can be skipped. You may need to post a more complete demo, I can only point to the documentation here. – Don McCurdy Apr 12 '17 at 18:08
  • Ok, yes that is an empty mesh, with empty geometry. The OBJ model has not loaded yet. If you listen for the `model-loaded` event and then check for the mesh, your model will have loaded and the real geometry should be there. – Don McCurdy Apr 12 '17 at 21:23
  • It didn't work because "mesh" is not null even when not populated. But checking for `if (!mesh.children.length)` does work - though there's probably a better "official" thing to check. I'll commit the changes to github in case you want a chuckle out of the console.log()s – Scott Singer Apr 14 '17 at 00:54