This contribution is a bugfix to ThreeJS Force-Directed Graph Javascript library authored by @vasturiano. It is a WebGL subclass of three.js Javascript 3D library to represent graph data in 3-dimensional geometry using force-directed physics.
Repository
https://github.com/vasturiano/three-forcegraph

Lastly I was studying how to interact with 3d-oriented graph data using three.js and @vasturiano's 3D Force-Directed Graph. During building complex data structues I decided to represent some of graph nodes as BoxGeometry
Although the task is simple, I couldn't get it to work.
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var cube = new THREE.Mesh( geometry, material );
scene.add( cube );
Above code works fine. The difference occurs when I had to set an array of materials to describe each of 6-side box separately - THREE.Mesh
allows this kind of usage but it bring unexpected consequences.
Issue
.nodeThreeObject(node => {
var box = new THREE.BoxGeometry(10, 10, 10);
var materials = [
new THREE.MeshStandardMaterial({color: 'red'}),
new THREE.MeshStandardMaterial({color: 'green'}),
new THREE.MeshStandardMaterial({color: 'blue'}),
new THREE.MeshStandardMaterial({color: 'cyan'}),
new THREE.MeshStandardMaterial({color: 'magenta'}),
new THREE.MeshStandardMaterial({color: 'yellow'}),
];
// 'materials' is of type Array()
return new THREE.Mesh(box, materials);
});
https://gist.github.com/mys/ff6100af32790ed99890cf4378a14020
If we set custom cube, set of more than one material and modify graphData
after, error occurs:

Through reversing code libraries and picking out whether it is issue of Texture
class, Material
or Mesh
I have finally found dispose()
function throwing error:
// Clear the scene
for (var t = function t(e) {
e.geometry && e.geometry.dispose(),
e.material && e.material.dispose(), << error
e.texture && e.texture.dispose(),
e.children && e.children.forEach(t)
It seemed that e.material
was type of Array(). Like we all know, javascript arrays don't have dispose() activity. All is clear now.
@vasturiano's comment: Ah, I wasn't aware a mesh could have an array of materials. Neat.
Solution
My idea was to check whether we deal with an array or object type. Then each children element (material) dispose in a loop.
if (obj.material) {
if (Array.isArray(obj.material)) {
obj.material.forEach(material => {
material.dispose();
});
}
else {
obj.material.dispose();
}
}
@vasturiano's did only one correction for performance. instanceof Array
is much more effective than isArray()
. Often we deal with tens of thousands objects iteracting each other. Every single performance is significant in 3D rendering.
Good to know there is much difference between instanceof Array
and isArray()
, even if they give same result.
I don't mind if project's author merged this code by himself. I just wanted to make sure this library suit my needs for my new Steem project (incoming).
if (obj.material) { obj.material instanceof Array ? obj.material.forEach(m => m.dispose()) : obj.material.dispose(); }
Final change
