Thanks Thomas! OK, we're in business.
To help me see what's going on, I built a basic set of "axes" using a line plotter algorithm, and I put these at the centre of the "Hello World" spinning cube demo (i.e. all centred at (0,0,0)), made the cube a bit transparent so that you can see everything. There's also a little Cone at the end of the x-axis. That is there simply to help you work out which way everything is pointing.

First, I create a quad, add it to world and as child of box, but I don't "build()" it:
//box and axes already created, omitted for space
Object3D label = new Object3D(2);
SimpleVector upperLeft=new SimpleVector(0,-1,0);
SimpleVector upperRight=new SimpleVector(1,-1,0);
SimpleVector lowerLeft=new SimpleVector(0,0,0);
SimpleVector lowerRight=new SimpleVector(1,0,0);
// Front
label.addTriangle(upperLeft,0,0, lowerLeft,0,1, upperRight,1,0);
label.addTriangle(upperRight,1,0, lowerLeft,0,1, lowerRight,1,1);
//label.setTexture("demo texture");
label.setBillboarding(true);
world.addObject(label);
box.addChild(label);
box.build();
//label.build();
i.e. it creates a square quad with lower-left corner at (0,0,0). The quad doesn't move, the cube and axes spin round it. So far so good:

But obviously this is no use if I want a label, as I have to texture it. So I "setTexture()" and "build()" by uncommenting those lines in the listing above. My texture is terrible, but that's not the real problem here

When I run the programme I see this:

The label is now "off centre" and I cannot understand why. It moves in a weird way that is hard to describe, like it is eccentric to (0,0,0). It seems that "build()" is doing this, rather than the texturing step.
In order to try to understand this better, I moved the camera round to (0,-6,0) to get a "plan" view. Then I see the following, without "build()":

With "build()":

I added the red circle myself - that is the "attachment" point, i.e. the billboard pivots around this point (looks like (0,0,0.5) in cube-space) as the whole cube assembly spins.
Since I've not done any translations, I am a bit confused by this! I cannot see why it would make any difference just to do the "build()" and it certainly doesn't give the result I would expect. Any explanations of what is happening here would be most welcome.