Hi again
Below, I’ve put in a simple code example of how I have ported Nehes bitmap font code example to a project. The project contains a rotating square to show that the openGL canvas can contain graphic:
Using the debugger I found that the font loading is working correctly!
Btw. I’m working on a spectrum analyser application a need to add text to the frequency and dB axis. If this can be done much simpler I’m open for suggestions
Looking forward to hear from you!
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <cstdio>
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>
#include "../../../juce.h"
#include "fftw3.h"
double PI = 3.14159265358979;
float rot;
// Copied from Nehes bitmap font tutorial 13
HDC hDC=NULL; // Private GDI Device Context
HGLRC hRC=NULL; // Permanent Rendering Context
HWND hWnd=NULL; // Holds Our Window Handle
HINSTANCE hInstance; // Holds The Instance Of The Application
GLuint base; // Base Display List For The Font Set
GLfloat cnt1; // 1st Counter Used To Move Text & For Coloring
GLfloat cnt2; // 2nd Counter Used To Move Text & For Coloring
// ------------------------------------------
class OpenGLCanvas : public OpenGLComponent,
public Timer
{
public:
OpenGLCanvas()
{
rot = 0;
startTimer(40);
}
~OpenGLCanvas()
{
}
void newOpenGLContextCreated()
{
// Copied from Nehes bitmap font tutorial 13
rot = 0;
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
BuildFont();
// ------------------------------------------
}
void renderOpenGL()
{
gluPerspective (45.0f,
this->getWidth() / (GLfloat) this->getHeight(),
0.1f,
100.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer
glLoadIdentity(); // Reset The Current Modelview Matrix
glTranslatef(0.0f,0.0f,-1.0f); // Move One Unit Into The Screen
glRotatef(rot,0,0,1.0f);
glColor3f(1.0f,0.0f,0.0f);
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
glBegin(GL_POLYGON);
glVertex3f (0.25f, 0.25f, -0.01f);
glVertex3f (0.75f, 0.25f, -0.01f);
glVertex3f (0.75f, 0.75f, -0.01f);
glVertex3f (0.25f, 0.75f, -0.01f);
glEnd();
rot += 1;
// Copied from Nehes bitmap font tutorial 13
glColor3f(1.0f*float(cos(cnt1)),1.0f*float(sin(cnt2)),1.0f-0.5f*float(cos(cnt1+cnt2)));
glRasterPos2f(-0.45f+0.05f*float(cos(cnt1)), 0.32f*float(sin(cnt2)));
glPrint("Active OpenGL Text With NeHe - %7.2f", cnt1); // Print GL Text To The Screen
cnt1+=0.051f; // Increase The First Counter
cnt2+=0.005f; // Increase The First Counter
// ------------------------------------------
}
void resized()
{
}
void timerCallback()
{
repaint();
}
// Copied from Nehes bitmap font tutorial 13
void BuildFont(void) // Build Our Bitmap Font
{
HFONT font; // Windows Font ID
HFONT oldfont; // Used For Good House Keeping
base = glGenLists(96); // Storage For 96 Characters
font = CreateFont( -24, // Height Of Font
0, // Width Of Font
0, // Angle Of Escapement
0, // Orientation Angle
FW_BOLD, // Font Weight
FALSE, // 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
"Courier New"); // Font Name
oldfont = (HFONT)SelectObject(hDC, font); // Selects The Font We Want
wglUseFontBitmaps(hDC, 32, 96, base); // Builds 96 Characters Starting At Character 32
SelectObject(hDC, oldfont); // Selects The Font We Want
DeleteObject(font); // Delete The Font
}
void KillFont(void) // Delete The Font List
{
glDeleteLists(base, 96); // Delete All 96 Characters
}
void glPrint(const char *fmt, ...) // Custom GL "Print" Routine
{
char text[256]; // Holds Our String
va_list ap; // Pointer To List Of Arguments
if (fmt == NULL) // If There's No Text
return; // Do Nothing
va_start(ap, fmt); // Parses The String For Variables
vsprintf_s(text, fmt, ap); // And Converts Symbols To Actual Numbers
va_end(ap); // Results Are Stored In Text
glPushAttrib(GL_LIST_BIT); // Pushes The Display List Bits
glListBase(base - 32); // Sets The Base Character to 32
glCallLists(strlen(text), GL_UNSIGNED_BYTE, text); // Draws The Display List Text
glPopAttrib(); // Pops The Display List Bits
}
// ------------------------------------------
};
//==============================================================================
/** This is the component that sits inside the "hello world" window, filling its
content area. In this example, we'll just write "hello world" inside it.
*/
class WindowContent : public Component,
public Timer
{
OpenGLCanvas* myOpenGLCanvas;
public:
WindowContent()
{
// Setup OpenGl component
myOpenGLCanvas = new OpenGLCanvas();
addAndMakeVisible(myOpenGLCanvas);
myOpenGLCanvas->makeCurrentContextActive();
myOpenGLCanvas->broughtToFront();
}
~WindowContent()
{
deleteAllChildren ();
}
void paint (Graphics& g)
{
}
void resized()
{
int x = this->getWidth();
int y = this->getHeight();
myOpenGLCanvas->setBounds(0,0,x,y);
}
void timerCallback()
{
repaint();
}
};
//==============================================================================
/** This is the top-level window that we'll pop up. Inside it, we'll create and
show a HelloWorldContentComponent component.
*/
class MainWindow : public DocumentWindow
{
public:
//==============================================================================
MainWindow()
: DocumentWindow (T("DSP App"),
Colours::lightgrey,
DocumentWindow::allButtons,
true)
{
setContentComponent(new WindowContent());
setVisible (true);
// centre the window on the desktop with this size
centreWithSize (800, 800);
setResizable(true,true);
setResizeLimits(800,800,1600,1024);
}
~MainWindow()
{
// (the content component will be deleted automatically, so no need to do it here)
}
//==============================================================================
void closeButtonPressed()
{
// When the user presses the close button, we'll tell the app to quit. This
// window will be deleted by the app object as it closes down.
JUCEApplication::quit();
}
};
//==============================================================================
/** This is the application object that is started up when Juce starts. It handles
the initialisation and shutdown of the whole application.
*/
class MainSetup : public JUCEApplication
{
/* Important! NEVER embed objects directly inside your JUCEApplication class! Use
ONLY pointers to objects, which you should create during the initialise() method
(NOT in the constructor!) and delete in the shutdown() method (NOT in the
destructor!)
This is because the application object gets created before Juce has been properly
initialised, so any embedded objects would also get constructed too soon.
*/
MainWindow* mainWindow;
public:
//==============================================================================
MainSetup()
: mainWindow (0)
{
// NEVER do anything in here that could involve any Juce function being called
// - leave all your startup tasks until the initialise() method.
}
~MainSetup()
{
// Your shutdown() method should already have done all the things necessary to
// clean up this app object, so you should never need to put anything in
// the destructor.
// Making any Juce calls in here could be very dangerous...
}
//==============================================================================
void initialise (const String& commandLine)
{
// just create the main window...
mainWindow = new MainWindow();
/* ..and now return, which will fall into to the main event
dispatch loop, and this will run until something calls
JUCEAppliction::quit().
In this case, JUCEAppliction::quit() will be called by the
hello world window being clicked.
*/
}
void shutdown()
{
// clear up..
if (mainWindow != 0)
delete mainWindow;
}
//==============================================================================
const String getApplicationName()
{
return T("test...");
}
const String getApplicationVersion()
{
return T("1.0");
}
bool moreThanOneInstanceAllowed()
{
return true;
}
void anotherInstanceStarted (const String& commandLine)
{
}
};
//==============================================================================
// This macro creates the application's main() function..
START_JUCE_APPLICATION (MainSetup)