Здравствуйте LtS, Вы писали:
LtS> Спасибо за ответ,
S>>1. это плохая идея, не стоит так делать
LtS> А какая идея будет получше, если хочется повыводить достаточно простыми методами с достаточным уровнем предсказуемости результатов двумерную графику совместно с трёхмерной.
ПОнятно. У OpenGL точнее его куска под Windows есть чудесная функция wglBuildFontBitmaps.
Она по выбраному на данный момент в DC шрифту строит растровые изображения и кидает их в displayList-ы.
Потом ими можно очень просто выводить текст.
Вот привожу класс обертку для писания шрифтом в OpenGL
GLFont.h
// GLFont.h: interface for the CGLFont class.
//
//////////////////////////////////////////////////////////////////////
#if !defined(AFX_GLFONT_H__563EFF12_A150_47EB_86C1_6F1E2B420978__INCLUDED_)
#define AFX_GLFONT_H__563EFF12_A150_47EB_86C1_6F1E2B420978__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include <gl\gl.h>
#include <stdarg.h>
#include "vector.hpp"
class CGLFont
{
public:
bool Print(const dvector dvPos, const char *fmt, ...);
CSize GetTextSize(LPCTSTR pText);
bool VerifyContext();
bool Create(TCHAR* szFaceName = "Arial", int iHeight = -12, bool bBold=false, bool bItalic=false);
bool KillFont();
CGLFont();
virtual ~CGLFont();
private:
HGLRC m_hNativeGLRC; // Holds HGLRC in which the font has been created
HDC m_hNativeDC; // Holds HGLRC in which the font has been created
bool m_bFontCreated;
GLuint m_uiBase;
HFONT m_hFont;
};
#endif // !defined(AFX_GLFONT_H__563EFF12_A150_47EB_86C1_6F1E2B420978__INCLUDED_)
// GLFont.cpp: implementation of the CGLFont class.
//
// Purpose: OpenGL raster font wrapper
// Author: Alexander Bijamov aka Sasparella
// Created: N/A
//
// Last Modified: 10 April 2002 by A. Bijamov.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GLFont.h"
#include "OpenGL.h"
#include "routines.h"
#include <gl\gl.h>
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
#define NUM_CHARACTERS 96
CGLFont::CGLFont()
{
m_hNativeGLRC = NULL;
m_hNativeDC = NULL;
m_bFontCreated = false;
m_hFont = NULL;
}
CGLFont::~CGLFont()
{
KillFont();
}
bool CGLFont::Create(TCHAR *szFaceName, int iHeight, bool bBold, bool bItalic)
{
if (m_bFontCreated && (!KillFont())) return false; // could not kill font - probably different context
HDC hDC = ::wglGetCurrentDC();
if (!hDC) return false;
m_hFont = CreateFont(iHeight,
0, // Width Of Font
0, // Angle Of Escapement
0, // Orientation Angle
bBold? FW_BOLD:FW_NORMAL, // Font Weight
bItalic, // Italic
FALSE, // Underline
FALSE, // Strikeout
ANSI_CHARSET, // Character Set Identifier
OUT_TT_PRECIS, // Output Precision
CLIP_DEFAULT_PRECIS, // Clipping Precision
ANTIALIASED_QUALITY, // Output Quality
FF_DONTCARE|DEFAULT_PITCH, // Family And Pitch
szFaceName); // Font Name
if (!m_hFont)
{
DisplayErrorMessage("CreateFont");
return false;
}
m_uiBase = glGenLists(NUM_CHARACTERS);
HFONT hOldFnt = (HFONT)SelectObject(hDC, (HGDIOBJ)m_hFont); // Selects The Font We Want
VERIFY(wglUseFontBitmaps(hDC, 32, NUM_CHARACTERS, m_uiBase)); // Builds 96 Characters Starting At Character 32
glFlush();
SelectObject(hDC, (HGDIOBJ)hOldFnt);
m_hNativeGLRC = :: wglGetCurrentContext();
m_hNativeDC = hDC;
m_bFontCreated = true;
return true;
}
bool CGLFont::KillFont()
{
//if (!VerifyContext()) return false; // you try to kill font, but you did not create it...
if (!m_bFontCreated) return false;
CToggleContext tc(m_hNativeDC, m_hNativeGLRC);
ASSERT(::wglGetCurrentContext());
glDeleteLists(m_uiBase, NUM_CHARACTERS);
DeleteObject(m_hFont);
m_bFontCreated = false;
return true;
}
bool CGLFont::VerifyContext()
{
return (m_bFontCreated && ::wglGetCurrentContext()==m_hNativeGLRC && ::wglGetCurrentDC()==m_hNativeDC );
}
CSize CGLFont::GetTextSize(LPCTSTR pText)
{
if (!m_bFontCreated) return CSize(0,0);
HFONT hOldFnt = (HFONT)SelectObject(m_hNativeDC, (HGDIOBJ)m_hFont);
CDC* pDC = CDC::FromHandle(m_hNativeDC);
CSize size = pDC->GetTextExtent(CString(pText));
SelectObject(m_hNativeDC, (HGDIOBJ)hOldFnt);
return size;
}
bool CGLFont::Print(const dvector dvPos, const char *fmt, ...)
{
if (!VerifyContext()) return false;
char text[256];
va_list ap;
if (fmt == NULL)
return true;
va_start(ap, fmt);
vsprintf(text, fmt, ap);
va_end(ap);
glRasterPos3d(dvPos.x,dvPos.y,dvPos.z);
glPushAttrib(GL_LIST_BIT);
glListBase(m_uiBase - 32);
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text);
glPopAttrib();
return true;
}
и вспомогательный клсаа
class CToggleContext
{
public:
~CToggleContext();
CToggleContext(HDC hDC, HGLRC hGLRC);
private:
HGLRC m_hMemoGLRC;
HDC m_hMemoDC;
};
CToggleContext::CToggleContext(HDC hDC, HGLRC hGLRC)
{
m_hMemoDC = wglGetCurrentDC();
m_hMemoGLRC = wglGetCurrentContext();
if (!wglMakeCurrent(hDC,hGLRC))
DisplayErrorMessage("MakeCurrent");
}
CToggleContext::~CToggleContext()
{
if (!wglMakeCurrent(m_hMemoDC,m_hMemoGLRC)) DisplayErrorMessage("MakeCurrent");
}
Кажись все понятно должно быть.
В классе вашего OpenGL окна созда5ете CGLfont glFont;
в инициализации после инита контекста вызываете glFont.Create(....)
а в очистке — glFont.KillFont() (до убивания контекста)
Рисовать —
glFont.Print(const dvector dvPos, const char *fmt, ...);
dvPos — это обычные координаты, как у glVertex. В этом месте и будет выведен текси.
Enjoy.
Саша.