voila, cette source permet d'ecrire tu texte en 3D
Source / Exemple :
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#ifndef _UTIL_H_
#include "util.h"
#endif // _UTIL_H_
#ifndef _MATH_H_
#include "math.h"
#endif // _MATH_H_
//------------------------------------------------------------
typedef struct tagRECT_FLOAT
{
FLOAT x,y,cx,cy;
}RECT_FLOAT,*P_RECT_FLOAT,**PP_RECT_FLOAT;
//------------------------------------------------------------
#define EPSILON 0.001
#define TIME_PER_TURN 10
//------------------------------------------------------------
#define MY_NUM_NAMES 4
#define MY_NUM_STRING 1000
//------------------------------------------------------------
void RePaint(HDC DC,double zoom,double theta,double phi)
{
static double q;
if(TRUE)
{
static DWORD oldCall;
DWORD t;
t = GetTickCount();
q += (360.*((double)(t - oldCall)))/(1000.*((double)TIME_PER_TURN));
oldCall = t;
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glPushAttrib(GL_CURRENT_BIT);
// position de l'oeil
gluLookAt(zoom*cos(theta)*cos(phi),zoom*sin(theta)*cos(phi),zoom*sin(phi),0,0,0,cos(theta-PI)*cos(PI/2.-phi),sin(theta-PI)*cos(PI/2.-phi),sin(PI/2.-phi));
glBegin(GL_LINES);
glColor3d(1.,1.,1.);
// axes
glVertex3d(-500,0,0);
glVertex3d(+500,0,0);
glVertex3d(0,-500,0);
glVertex3d(0,+500,0);
glVertex3d(0,0,-500);
glVertex3d(0,0,+500);
glEnd();
// les noms
if(TRUE)
{
glPushMatrix();
glRotated(q,1,0,0);
glCallList(MY_NUM_NAMES);
glPopMatrix();
}
// fin du dessinage
glPopAttrib();
glPopMatrix();
SwapBuffers(DC);
}
//------------------------------------------------------------
void InitPixelFormat(HDC hdc)
{
PIXELFORMATDESCRIPTOR pfd = {sizeof (PIXELFORMATDESCRIPTOR),1,PFD_SUPPORT_OPENGL | PFD_TYPE_RGBA | PFD_DRAW_TO_WINDOW | PFD_DOUBLEBUFFER,16,0,0,0,0,0,0,0,0,0,0,0,0,0,16,0,0,0,0,0,0,0};
SetPixelFormat(hdc,ChoosePixelFormat(hdc,&pfd),&pfd);
}
//------------------------------------------------------------
void CreatePave(double a,double b,double c)
{
glBegin(GL_QUAD_STRIP);
glVertex3d(-a,+b,-c);
glVertex3d(+a,+b,-c);
glVertex3d(-a,-b,-c);
glVertex3d(+a,-b,-c);
glVertex3d(-a,-b,+c);
glVertex3d(+a,-b,+c);
glVertex3d(-a,+b,+c);
glVertex3d(+a,+b,+c);
glVertex3d(-a,+b,-c);
glVertex3d(+a,+b,-c);
glEnd();
glBegin(GL_QUADS);
glVertex3d(-a,-b,-c);
glVertex3d(-a,+b,-c);
glVertex3d(-a,+b,+c);
glVertex3d(-a,-b,+c);
glVertex3d(+a,-b,-c);
glVertex3d(+a,+b,-c);
glVertex3d(+a,+b,+c);
glVertex3d(+a,-b,+c);
glEnd();
}
//------------------------------------------------------------
int MyCalcText(GLYPHMETRICSFLOAT *pGmf,char *text,P_RECT_FLOAT pRect)
{
int len;
FLOAT cx,cy;
FLOAT tX,tY; // tranlation
len = 0;
cx = 0.;
cy = 0.;
tX = 0.;
tY = 0.;
while(*text != '\0')
{
GLYPHMETRICSFLOAT *p;
p = pGmf + ((unsigned char)*text);
cx += p->gmfCellIncX;
cy = max(cy,p->gmfBlackBoxY);
tY = min(tY,(p->gmfptGlyphOrigin.y)-cy);
text ++;
len ++;
}
// l'eventuelle translation
pRect->x = tX;
pRect->y = tY;
// la largeur
pRect->cx = cx;
pRect->cy = cy;
return len;
}
//------------------------------------------------------------
void PrintTextInBox(GLYPHMETRICSFLOAT *pGmf,char *text,FLOAT trueCx,FLOAT trueCy)
{
int len;
RECT_FLOAT rc;
glPushMatrix();
len = MyCalcText(pGmf,text,&rc);
glTranslated(-rc.x,-rc.y,0.);
glScalef(trueCx/rc.cx,trueCy/rc.cy,1.);
glListBase(MY_NUM_STRING);
glCallLists(len,GL_UNSIGNED_BYTE,text);
glPopMatrix();
}
//------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hwnd,UINT iMsg,WPARAM wParam,LPARAM lParam)
{
static HDC hdc;
static HGLRC hrc;
static int cxClient,cyClient;
static double zoom,theta,phi,_theta,_phi;
static BOOL isMouseDown;
static int xMouseStart,yMouseStart;
static HFONT font,oldFont;
// traitement des messages
switch (iMsg)
{
case WM_CREATE:
{
GLYPHMETRICSFLOAT gmf[256];
hdc=GetDC(hwnd);
InitPixelFormat(hdc);
hrc = wglCreateContext(hdc);
wglMakeCurrent(hdc,hrc);
glEnable(GL_DEPTH_TEST);
glClearColor(0,0,0,0);
font = CreateFont(
40,
30,
0, // inclinaison du texte
0, // genre 'italique programmable'
1, // graisse
FALSE, // italic
FALSE, // souligne
FALSE, // barre
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLIP_DEFAULT_PRECIS,
DEFAULT_QUALITY,
VARIABLE_PITCH+FF_SWISS,
"Arial"
);
Assert(NULL != font);
oldFont = SelectObject(hdc,font);
// create bitmaps for the device context font's first 256 glyphs
if(!wglUseFontOutlines(
hdc,
0,
256,
1000,
0.01F,
5.F,
WGL_FONT_POLYGONS,
gmf
)
)
{
Error((NULL));
}
// creation des noms
if(TRUE)
{
char *tabName[] = {
"jcdJCD",
"Texte en OpenGL",
"www.cppfrance.com",
"Vive le langage C/C++"
};
int i;
glNewList(MY_NUM_NAMES,GL_COMPILE);
glPushMatrix();
glColor3d(1.,0.,0.);
CreatePave(500.,70.,70.);
glPopMatrix();
glColor3d(1.,1.,1.);
for(i=0;i<4;i++)
{
glPushMatrix();
glRotated(((double)i)*90.,1.,0.,0.);
glTranslated(-450.,-40.,75.);
PrintTextInBox(gmf,tabName[i],900.,80.);
glPopMatrix();
}
glEndList();
}
zoom = 1400.;
// on veut les coordonnees de l'ecran (meme direction)
theta = -PI/2;
phi = -PI/2;
break;
}
case WM_SIZE:
{
double r;
cxClient = LOWORD(lParam); cxClient = (cxClient ? cxClient : 1);
cyClient = HIWORD(lParam); cyClient = (cyClient ? cyClient : 1);
glViewport(0,0,cxClient,cyClient);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
if(1 > (r = (float)(cxClient)/(float)(cyClient)))
{
//r = (float)(cyClient)/(float)(cxClient);
}
gluPerspective(45.,r,100.,100000.);
break;
}
case WM_CHAR:
{
switch((char)wParam)
{
case 'a':
{
zoom -= 10.;
return 0;
}
case 'q':
{
zoom += 10.;
return 0;
}
}
break;
}
case WM_LBUTTONDOWN:
{
xMouseStart = LOWORD(lParam);
yMouseStart = HIWORD(lParam);
// on sauvegarde les angles
_theta = theta;
_phi = phi;
isMouseDown = TRUE;
SetCapture(hwnd);
return 0;
}
case WM_LBUTTONUP:
{
if(isMouseDown)
{
ReleaseCapture();
isMouseDown = FALSE;
}
return 0;
}
case WM_MOUSEMOVE:
{
if(isMouseDown)
{
int x,y;
x = (int) (__int16) LOWORD(lParam);
y = (int) (__int16) HIWORD(lParam);
// attention, comme les coordonnees en Y
// client sont inversees (de haut en bas)
// il faut faire -, et non +
// comme pout le X
theta = _theta + ((xMouseStart - x)*2*PI)/(double)cxClient;
phi = _phi - ((yMouseStart - y)*2*PI)/(double)cyClient;
}
return 0;
}
case WM_PAINT:
{
RePaint(hdc,zoom,theta,phi);
return 0;
}
case WM_DESTROY:
{
DeleteObject(SelectObject(hdc,oldFont));
glDeleteLists(MY_NUM_NAMES ,1);
// delete our 256 glyph display lists
glDeleteLists(MY_NUM_STRING, 256);
wglMakeCurrent(NULL, NULL);
wglDeleteContext(hrc);
ReleaseDC(hwnd,hdc);
PostQuitMessage(0);
break;
}
}
return DefWindowProc(hwnd,iMsg,wParam,lParam);
}
//------------------------------------------------------------
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int CmdShow)
{
WNDCLASS wc;
MSG msg;
HWND hWnd;
srand((unsigned)GetTickCount());
wc.style = CS_OWNDC;
wc.lpfnWndProc = WindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = NULL;
wc.lpszClassName = "jcdText";
RegisterClass(&wc);
hWnd = CreateWindow("jcdText","Texte en OpenGL",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
NULL,NULL,hInstance,NULL
);
ShowWindow(hWnd,SW_SHOWMAXIMIZED);
UpdateWindow(hWnd);
while(GetMessage(&msg,NULL,0,0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
Conclusion :
les lettres avec des "pieds" comme j,q,p .... ne sont pas pris en compte, il ne sont pas dans le rectangle