three.js - How to keep objects linked when moving one of them?

2.1k views Asked by At

I am trying to represent a graph with three.js, where nodes objects can be moved with click-and-drag. My current problem is that the edges, created as THREE.Line going from one node to another, don't move with the node (edges should rotate / change length).

My code so far:

var colour = 0x568c4b, geometry = new THREE.BoxGeometry(size, size, size),
    material = new THREE.MeshLambertMaterial({ color: colour }),
    position0 = new THREE.Vector3(-100, -60, 0),
    position1 = new THREE.Vector3(150, 50, 0);

node0 = new THREE.Mesh(geometry, material);
node0.position = position0;
scene.add(node0);
objects.push(node0);

node1 = new THREE.Mesh(geometry, material);
node1.position = position1;
scene.add(node1);
objects.push(node1);

var edge_def = new THREE.Geometry();

/*
 * How to refresh this so that 'edge0' is always connected to 'node0' and 'node1'?
 */
edge_def.vertices.push(node0.position);
edge_def.vertices.push(node1.position);
/*
 */

edge_def.colors.push(new THREE.Color(colour));
edge_def.colors.push(new THREE.Color(colour));
edge0 = new THREE.Line(edge_def, new THREE.LineBasicMaterial({
    linewidth: 5,
    vertexColors: true
}));
scene.add(edge0);

Here is a jsfiddle of what I have done (as I am currently learning how to use three.js, my code is heavily based on the draggable cubes (www.threejs.org/examples/#webgl_interactive_draggablecubes) example from threejs.org). As you can see, dragging a node cube lets the edge unchanged when it should always be connected.

So if you could help by pointing me to resources or examples on how to do that, I would be very thankful.

EDIT: This is what I try to do, with pictures.

2

There are 2 answers

0
lot On BEST ANSWER

Your problem is caused by the fact that THREE.JS caches almost everything for performance reasons. Including geometries. You have to tell the renderer that line geometry has changed by setting geometry's property verticesNeedUpdate to true.

I updated your jsFiddle code, so you should see it working now.

there is only one extra line of code needed in your onDocumentMouseMove function:

if (SELECTED) {
    intersects = raycaster.intersectObject(plane);
    SELECTED.position.copy(intersects[0].point.sub(offset));
    edge0.geometry.verticesNeedUpdate = true; //THIS WILL TELL RENDERER THAT GEOMETRY HAS CHANGED
    return;
}
2
lot On

(This is actually not aswering the original question, because I misunderstood it. But when I realized that, it was already marked as useful by 3 people, so I am keeping it here for people looking for answer of a little different question ;-)

If anybody wants to move all objects together as one, then use Object3D as a wrapper and then move that wrapper.

var wrapper = new THREE.Object3D();
wrapper.add(node0);
wrapper.add(node1);
wrapper.add(edge0);
scene.add(wrapper);

In this case you don't insert your meshes into scene directly, but rather whole wrapper.