PDA

View Full Version : Icon drawing in 3d



anopgl
08-19-2011, 12:57 PM
Hi

I'm drawing some 2d icons in 3d game using billboarding(they should always face the camera). They purpose is to sign specific places in the scene.
How can I keep icon(image ) sizes small and correct looking while drawing in 3d perspective projection? Is there any known relation between original icon size in pixels and the size to to be given in 3d metric space?

Thanks

Ilian Dinev
08-19-2011, 03:21 PM
try:


You have:
vec3 IconPos; // where the icon is
mat4 mvp; // model-view-projection matrix
float invWidth = 1.0/640;
float invHeight= 1.0/480;
int iconSize=32; // if you want to see it always 32x32px big
//-----------------
vec4 clip = mvp * vec4(IconPos,1.0);
float dx = iconSize * invWidth * 0.5 * clip.w;
float dy = iconSize * invHeight * 0.5 * clip.w;


vec4 vout[4];
vout[0] = vec4(clip.x - dx, clip.y + dy, clip.z,clip.w);
vout[1] = vec4(clip.x - dx, clip.y - dy, clip.z,clip.w);
vout[2] = vec4(clip.x + dx, clip.y - dy, clip.z,clip.w);
vout[3] = vec4(clip.x + dx, clip.y + dy, clip.z,clip.w);

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex4fv(&vout[0].x);
glTexCoord2f(0,1); glVertex4fv(&vout[1].x);
glTexCoord2f(1,1); glVertex4fv(&vout[2].x);
glTexCoord2f(1,0); glVertex4fv(&vout[3].x);
glEnd();

BionicBytes
08-22-2011, 04:57 PM
@llian,
I tried the code you posted and it works very, very well. :eek:

How did you ever figure out that:


vout[0] = vec4(clip.x - dx, clip.y + dy, clip.z,clip.w);
vout[1] = vec4(clip.x - dx, clip.y - dy, clip.z,clip.w);
vout[2] = vec4(clip.x + dx, clip.y - dy, clip.z,clip.w);
vout[3] = vec4(clip.x + dx, clip.y + dy, clip.z,clip.w);

would ever work?

Alfonse Reinheart
08-22-2011, 07:01 PM
I'm guessing he employed math ;) All he's doing is computing positions that will effectively reverse the perspective projection, thus keeping it at the correct size.

Ilian Dinev
08-23-2011, 12:24 AM
I figured the 4 vertices should have the same z and w, and backtraced how to "unproject" xy.

BionicBytes
08-23-2011, 01:48 AM
I can see you were unprojecting the icon position into clip space, but the next step you took was a stroke of genius in my opinion as it's not immediately obvious to me that the key to this technique is dx * clip.w to 'perspectively' correct the icon size.

float dx = iconSize * invWidth * 0.5 * clip.w;
float dy = iconSize * invHeight * 0.5 * clip.w;

I suppose if you figure that the next step in the FF pipeline is to perform a perspective divide with a computed clip-space w (just as you did), then it all makes sense as you have just reversed the projection.

Anyway, well done!

anopgl
08-23-2011, 01:58 AM
Yes, MANY THANKS to Ilian. Sorry for late update. It solved my problem and seems like I'll use this approach a lot.

anopgl
08-29-2011, 02:49 AM
Hi
Sorry for bringing it up again.
But now I copied the code to another project where my metric space is relatively large[-2500,2500] and when I do rendering it doesnt work anymore. I can't see the icons anymore.
It looks like clip vector values are the problem.

Please take a look at my code:




GLfloat matProj[16];
GLfloat matModelProj[16];
float InvWidth = 1.0/winWidth;
float InvHeight= 1.0/winHeight;
float vClip[4],vPos[4] = {icon.x,icon.y,icon.fz,1.0f};

glBindTexture(GL_TEXTURE_2D, icon.TexID);
glEnable(GL_TEXTURE_2D);
glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glPushMatrix();


glGetFloatv(GL_PROJECTION_MATRIX, matProj);
glMultMatrixf(matProj);
glGetFloatv(GL_MODELVIEW_MATRIX,matModelProj);

//multiply modelview-proj matrix with position
Matrix4MultiplyByVector(matModelProj,vPos,vClip);
float dx = (float)icon.SizeX * (float)winWidth *0.5f * vClip[3];
float dy = (float)icon.SizeY * (float)winHeight *0.5f * vClip[3];

float vScr1[4] = {vClip[0] - dx, vClip[1] + dy, vClip[2],vClip[3]};
float vScr2[4] = {vClip[0] - dx, vClip[1] - dy, vClip[2],vClip[3]};
float vScr3[4] = {vClip[0] + dx, vClip[1] - dy, vClip[2],vClip[3]};
float vScr4[4] = {vClip[0] + dx, vClip[1] + dy, vClip[2],vClip[3]};


glPopMatrix();
glBegin(GL_QUADS);
glTexCoord2f(0,0); glVertex4fv(vScr1);
glTexCoord2f(0,1); glVertex4fv(vScr2);
glTexCoord2f(1,1); glVertex4fv(vScr3);
glTexCoord2f(1,0); glVertex4fv(vScr4);
glEnd();

glDisable(GL_BLEND);
glDisable(GL_TEXTURE_2D);



Thanks