You have a lot of nodes in 3D space (so x,y,z coordinates for each). You also have some of them linked (so integers a,b for each edge, where a and b are indexes of the arrays used to find the coordinates). All nodes repel each other in the following way for each a!=b
dx=x[b]-x[a]; dy=y[b]-y[a]; dz=z[b]-z[a]; // So (dx,dy,dz) is vector from a to b
dd=dx*dx+dy*dy+dz*dz; // I.e. distance^2 between a and b
x[a]-=dt*dx/dd; y[a]-=dt*dy/dd; z[a]-=dt*dz/dd;
x[b]+=dt*dx/dd; y[b]+=dt*dy/dd; z[b]+=dt*dz/dd;
...where dt is some scaling constant like 0.05 determining how quickly the rearrangement takes place. Setting it too high will make the mesh unstable, especially where one node is linked to a lot of others. This happens because the coordinates will tend to overshoot where they really ought to converge to, and the overcorrection happens even more the other way, etc. All nodes (a,b) connected by an EDGE are attracted to each other. The code is identical except that the += and -= are swapped over (attraction not repulsion) and "/dd" is removed - dt*dx, dt*dy etc. are just added. This makes for an attractive force like a rubber band, which increases proportional to distance whereas the repulsion actually decreases in inverse proportion to distance. This allows the linked nodes to attain an equilibrium when they are at a certain distance from each other, while the overall repulsion tends to spread things out nicely. Incidentally, this does not need to be 3D: you can do the same in 2D and it works well. (I've tried it in 4D with warped spacetime but that's a story for another day).
This is a good algorithm except that it's a bit slow because of all the repulsions (one for every possible pair of points): what I think I do in netview.exe to speed things up is to only repel points that are nearby each other by taking advantage of the graph linkage. Each point repels its direct neighbours in the mesh and the neighbours of its neighbours (without this second lot, there'd be no force to e.g. straighten out long chains). Actually this on its own works (iterates faster), but the iteration itself doesn't move the nodes quite as quick as I wanted, so in netview I also repel each point by 10 random other ones in the mesh, and this acts to also give an overall spreading-out effect.