Billboarding, almost there but not quite!

i’ve been trying for a while to get billboarding to work with lwjgl, i have been stuck trying to get the code below to work, especially with the vectors, with the code below i’m almost there but a bit stuck with it, i have tried to use the vector class that comes with lwjgl but probably doing it wrong, i’ve attached the code below any help would be appreciated

thx


import org.lwjgl.opengl.GL11;
import java.nio.FloatBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.vector.Vector3f;
...

public void draw(int x, int y, int z) {

// setup variables
Vector3f center = null; // this will be the center point of the quad
Vector3f right = null, up = null; // used to hold the x-right and y-up vectors
Vector3f a, b, c, d; // four corners of the quad

		
// set location of quad
GL11.glTranslatef(x, y, z);

GL11.glPushMatrix();

	FloatBuffer buf = BufferUtils.createFloatBuffer(16 * 4);

	// Get your current model view matrix from OpenGL. 
	GL11.glGetFloat(GL11.GL_MODELVIEW_MATRIX, buf);

	// rewind the buffer
        buf.rewind();


	// build vectors from model matrix
	right.set(buf.get(0), buf.get(4), buf.get(8));
	up.set(buf.get(1), buf.get(5), buf.get(9));


	// setup center variable, this is center point of the quad
	center.set(buf.get(12), buf.get(13), buf.get(14));


	// setup corners of quad to face camera
	a = center - (right + up) * size;
	b = center + (right - up) * size;
	c = center + (right + up) * size;
	d = center - (right - up) * size;


	// bind the texture of image to be displayed on quad
	texture.bind();

        GL11.glBegin(GL11.GL_QUADS);                     // Build Quad
        
            GL11.glTexCoord2f(1.0f, 1.0f); GL11.glVertex3fv(a); // Bottom Left
            GL11.glTexCoord2f(0.0f, 1.0f); GL11.glVertex3fv(b); // Bottom Right
            GL11.glTexCoord2f(1.0f, 0.0f); GL11.glVertex3fv(c); // Top Right
            GL11.glTexCoord2f(0.0f, 0.0f); GL11.glVertex3fv(d); // Top Left  
           
        GL11.glEnd();                                                  // Done Building Quad               
                              
GL11.glPopMatrix();
}

The translation portion of the matrix is stored in 3,0 3,1 3,2, like:

| 1 0 0 X |
| 0 1 0 Y |
| 0 0 1 Z |
| 0 0 0 1 |

That means the index 12, 13, 14 elements of your 16 float buffer.

so

center.set(buf.get(12), buf.get(13), buf.get(14));

thx for ur reply, but the thing is what is “center.set” is it an array or something and how is the calculation done to store there?

Oh I assumed center was a Vector3f. I now see you declared it as a float… I intended it as a vector.

ok thx for the update, if made the changes but i don’t think the Vector3f, class works as it should any idea?

Well I use Vector3f all the time with no problems. What isn’t working as it should? I notice you have some code in there:

// setup corners of quad to face camera
a = center - (right + up) * size;
b = center + (right - up) * size;
c = center + (right + up) * size;
d = center - (right - up) * size;

That looks like c++, Vector3f doesn’t support those operators.

ah i see, those bits are the problem:

// setup corners of quad to face camera
a = center - (right + up) * size;
b = center + (right - up) * size;
c = center + (right + up) * size;
d = center - (right - up) * size;

and

GL11.glVertex3fv(a); // Bottom Left
GL11.glVertex3fv(b); // Bottom Right
GL11.glVertex3fv©; // Top Right
GL11.glVertex3fv(d); // Top Left

i was using a c++ tutorial to get it working, so how would you do the same thing with lwjgl, or is there a different way?

thx

Unfortunately these operations are somewhat cumbersome with the Vector3f. Here’s one suggestion:


a = center - (right + up) * size;
b = center + (right - up) * size;
c = center + (right + up) * size;
d = center - (right - up) * size;


a.set(center.x - (right.x + up.x) * size, center.y - (right.y + up.y) * size,  center.z - (right.z + up.z) * size);

etc…

Or with a temporary:


JwVector3f tmp = new JwVector3f();
Vector3f.sub(center, (Vector3f)Vector3f.add(right, up, tmp).scale(size),  a);

It’s unfortunate that Vector3f.scale() returns as a Vector rather than Vector3f.

You should be able get away with using your result vector as your temporary, but I didn’t research it to make sure:


Vector3f.sub(center, (Vector3f)Vector3f.add(right, up, a).scale(size),  a);

You could also possibly save some time by precomputing stuff, at the expense of a little more storage. (You’d want to pre-allocate if you are doing this alot)



Vector3f rightPlusUp = (Vector3f)Vector3f.add(right, up, new Vector3f()).scale(size);
Vector3f rightMinusUp = (Vector3f)Vector3f.sub(right, up, new Vector3f()).scale(size);

Vector3f.sub(center, rightPlusUp, a);
Vector3f.add(center, rightMinusUp, b);
Vector3f.add(center, rightPlusUp, c);
Vector3f.sub(center, rightMinusUp, d);


Hope this rambling helps!