zoukankan      html  css  js  c++  java
  • GLUT Tutorials 12:位图字体

    博客转自:http://www.lighthouse3d.com/tutorials/glut-tutorial/bitmap-fonts/

    位图字体是一个2维的字体,虽然我们会将它放置在3维的世界内,但是这些字体没有厚度,不可以被旋转或者缩放;只可以被平移。而且,这种字体永远只朝向观测者的视野,就像看着宣传板一样。尽管这些特性是潜在的劣势,但是从另外一方面来看,我们不需要关心如何设置他的朝向使其朝向观测者的视野。

    在这个小节,我们将呈现 GLUT 如何将位图字体显示在屏幕上。我们需要使用函数 glutBitmapCharacter 去写一个字符。

    void glutBitmapCharacter(void *font, int character)
    
    Parameters:
    
    font – the name of the font to use (see bellow for a list of what’s available
    character – what to render, a letter, symbol, number, etc…

    The font options available are:

    • GLUT_BITMAP_8_BY_13
    • GLUT_BITMAP_9_BY_15
    • GLUT_BITMAP_TIMES_ROMAN_10
    • GLUT_BITMAP_TIMES_ROMAN_24
    • GLUT_BITMAP_HELVETICA_10
    • GLUT_BITMAP_HELVETICA_12
    • GLUT_BITMAP_HELVETICA_18

    想要观测各种字体的显示效果,可以尝试将所有字体类型都显示在弹出菜单中。下面的函数输出一个字符到当前光栅位置。

    glutBitmapCharacter(GLUT_BITMAP_HELVETICA_18,'3');

     需要解释一下光栅位置,我们可以通过函数OpenGL库中的 glRasterPos 函数设置光栅位置。

    void glRasterPos2f(float x, float y);
    void glRasterPos3f(float x, float y, float z);
    
    Parameters:
    
    x, y, z – local coordinates for the text to appear

    函数 glutBitmapCharacter 依据字符的宽度在指定位置渲染字符。因此,如果想渲染字符串,需要连续调用 glutBitmapCharacter 函数,将会得到想要的显示效果。下面是渲染字符串的例子

    void renderBitmapString(
            float x,
            float y,
            float z,
            void *font,
            char *string) {
    
      char *c;
      glRasterPos3f(x, y,z);
      for (c=string; *c != ''; c++) {
        glutBitmapCharacter(font, *c);
      }
    }

    完整代码如下

    #include <stdlib.h>
    #include <stdio.h>
    #include <math.h>
    
    #ifdef __APPLE__
    #include <GLUT/glut.h>
    #else
    #include <GL/glut.h>
    #endif
    
    // angle of rotation for the camera direction
    float angle = 0.0f;
    
    // actual vector representing the camera's direction
    float lx = 0.0f, lz = -1.0f;
    
    // XZ position of the camera
    float x = 0.0f, z = 5.0f;
    
    // the key states. These variables will be zero
    //when no key is being presses
    float deltaAngle = 0.0f;
    float deltaMove = 0;
    int xOrigin = -1;
    
    // Constant definitions for Menus
    #define RED 1
    #define GREEN 2
    #define BLUE 3
    #define ORANGE 4
    
    #define FILL 1
    #define LINE 2
    
    // Pop up menu identifiers
    int fillMenu, fontMenu, mainMenu, colorMenu;
    
    // color for the nose
    float red = 1.0f, blue = 0.5f, green = 0.5f;
    
    // scale of snowman
    float scale = 1.0f;
    
    // menu status
    int menuFlag = 0;
    
    // default font
    void *font = GLUT_BITMAP_TIMES_ROMAN_24;
    
    #define INT_GLUT_BITMAP_8_BY_13 1
    #define INT_GLUT_BITMAP_9_BY_15 2
    #define INT_GLUT_BITMAP_TIMES_ROMAN_10  3
    #define INT_GLUT_BITMAP_TIMES_ROMAN_24  4
    #define INT_GLUT_BITMAP_HELVETICA_10  5
    #define INT_GLUT_BITMAP_HELVETICA_12  6
    #define INT_GLUT_BITMAP_HELVETICA_18  7
    
    void changeSize(int w, int h) {
    
        // Prevent a divide by zero, when window is too short
        // (you cant make a window of zero width).
        if (h == 0)
            h = 1;
    
        float ratio = w * 1.0 / h;
    
        // Use the Projection Matrix
        glMatrixMode(GL_PROJECTION);
    
        // Reset Matrix
        glLoadIdentity();
    
        // Set the viewport to be the entire window
        glViewport(0, 0, w, h);
    
        // Set the correct perspective.
        gluPerspective(45.0f, ratio, 0.1f, 100.0f);
    
        // Get Back to the Modelview
        glMatrixMode(GL_MODELVIEW);
    }
    
    void drawSnowMan() {
    
        glScalef(scale, scale, scale);
        glColor3f(1.0f, 1.0f, 1.0f);
    
        // Draw Body
        glTranslatef(0.0f, 0.75f, 0.0f);
        glutSolidSphere(0.75f, 20, 20);
    
        // Draw Head
        glTranslatef(0.0f, 1.0f, 0.0f);
        glutSolidSphere(0.25f, 20, 20);
    
        // Draw Eyes
        glPushMatrix();
        glColor3f(0.0f, 0.0f, 0.0f);
        glTranslatef(0.05f, 0.10f, 0.18f);
        glutSolidSphere(0.05f, 10, 10);
        glTranslatef(-0.1f, 0.0f, 0.0f);
        glutSolidSphere(0.05f, 10, 10);
        glPopMatrix();
    
        // Draw Nose
        glColor3f(red, green, blue);
        glRotatef(0.0f, 1.0f, 0.0f, 0.0f);
        glutSolidCone(0.08f, 0.5f, 10, 2);
    
        glColor3f(1.0f, 1.0f, 1.0f);
    
    }
    
    void renderBitmapString(
        float x,
        float y,
        float z,
        void *font,
        char *string) {
        char *c;
        glRasterPos3f(x, y, z);
        for (c = string; *c != ''; c++) {
            glutBitmapCharacter(font, *c);
        }
    }
    
    void computePos(float deltaMove) {
    
        x += deltaMove * lx * 0.1f;
        z += deltaMove * lz * 0.1f;
    }
    
    void renderScene(void)
    {
        if (deltaMove)
            computePos(deltaMove);
    
        // Clear Color and Depth Buffers
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    
        // Reset transformations
        glLoadIdentity();
        
        // Set the camera
        gluLookAt(x, 1.0f, z,
            x + lx, 1.0f, z + lz,
            0.0f, 1.0f, 0.0f);
    
        // Draw ground
        glColor3f(0.9f, 0.9f, 0.9f);
        glBegin(GL_QUADS);
        glVertex3f(-100.0f, 0.0f, -100.0f);
        glVertex3f(-100.0f, 0.0f, 100.0f);
        glVertex3f(100.0f, 0.0f, 100.0f);
        glVertex3f(100.0f, 0.0f, -100.0f);
        glEnd();
    
        // Draw 36 SnowMen
        char number[3];
        for (int i = -3; i < 3; i++)
        {
            for (int j = -3; j < 3; j++)
            {
                glPushMatrix();
                glTranslatef(i*10.0f, 0.0f, j * 10.0f);
                drawSnowMan();
                sprintf(number, "%d", (i + 3) * 6 + (j + 3));
                renderBitmapString(0.0f, 0.5f, 0.0f, (void *)font, number);
                glPopMatrix();
            }
        }
            
        glutSwapBuffers();
    }
    
    // -----------------------------------
    //             KEYBOARD
    // -----------------------------------
    
    void processNormalKeys(unsigned char key, int xx, int yy)
    {
        switch (key) 
        {
        case 27:
            glutDestroyMenu(mainMenu);
            glutDestroyMenu(fillMenu);
            glutDestroyMenu(colorMenu);
            glutDestroyMenu(fontMenu);
            exit(0);
            break;
        }
    }
    
    void pressKey(int key, int xx, int yy)
    {
        switch (key) 
        {
        case GLUT_KEY_UP: deltaMove = 0.5f; break;
        case GLUT_KEY_DOWN: deltaMove = -0.5f; break;
        }
    }
    
    void releaseKey(int key, int x, int y)
    {
        switch (key) 
        {
        case GLUT_KEY_UP:
        case GLUT_KEY_DOWN: deltaMove = 0; break;
        }
    }
    
    // -----------------------------------
    //             MOUSE
    // -----------------------------------
    
    void mouseMove(int x, int y)
    {
        // this will only be true when the left button is down
        if (xOrigin >= 0) 
        {
            // update deltaAngle
            deltaAngle = (x - xOrigin) * 0.001f;
    
            // update camera's direction
            lx = sin(angle + deltaAngle);
            lz = -cos(angle + deltaAngle);
        }
    }
    
    void mouseButton(int button, int state, int x, int y) 
    {
        // only start motion if the left button is pressed
        if (button == GLUT_LEFT_BUTTON) {
    
            // when the button is released
            if (state == GLUT_UP) {
                angle += deltaAngle;
                xOrigin = -1;
            }
            else  {// state = GLUT_DOWN
                xOrigin = x;
            }
        }
    }
    
    // -----------------------------------
    //             MENUS
    // -----------------------------------
    
    void processMenuStatus(int status, int x, int y) 
    {
        if (status == GLUT_MENU_IN_USE)
            menuFlag = 1;
        else
            menuFlag = 0;
    }
    
    void processMainMenu(int option)
    {
        // nothing to do in here
        // all actions are for submenus
    }
    
    void processFillMenu(int option) 
    {
        switch (option) 
        {
        case FILL: glPolygonMode(GL_FRONT, GL_FILL); break;
        case LINE: glPolygonMode(GL_FRONT, GL_LINE); break;
        }
    }
    
    void processFontMenu(int option)
    {
        switch (option)
        {
        case INT_GLUT_BITMAP_8_BY_13:
            font = GLUT_BITMAP_8_BY_13;
            break;
        case INT_GLUT_BITMAP_9_BY_15:
            font = GLUT_BITMAP_9_BY_15;
            break;
        case INT_GLUT_BITMAP_TIMES_ROMAN_10:
            font = GLUT_BITMAP_TIMES_ROMAN_10;
            break;
        case INT_GLUT_BITMAP_TIMES_ROMAN_24:
            font = GLUT_BITMAP_TIMES_ROMAN_24;
            break;
        case INT_GLUT_BITMAP_HELVETICA_10:
            font = GLUT_BITMAP_HELVETICA_10;
            break;
        case INT_GLUT_BITMAP_HELVETICA_12:
            font = GLUT_BITMAP_HELVETICA_12;
            break;
        case INT_GLUT_BITMAP_HELVETICA_18:
            font = GLUT_BITMAP_HELVETICA_18;
            break;
        }
    }
    
    void processColorMenu(int option)
    {
        switch (option) {
        case RED:
            red = 1.0f;
            green = 0.0f;
            blue = 0.0f; break;
        case GREEN:
            red = 0.0f;
            green = 1.0f;
            blue = 0.0f; break;
        case BLUE:
            red = 0.0f;
            green = 0.0f;
            blue = 1.0f; break;
        case ORANGE:
            red = 1.0f;
            green = 0.5f;
            blue = 0.5f; break;
        }
    }
    
    void createPopupMenus() 
    {
        fontMenu = glutCreateMenu(processFontMenu);
    
        glutAddMenuEntry("BITMAP_8_BY_13 ", INT_GLUT_BITMAP_8_BY_13);
        glutAddMenuEntry("BITMAP_9_BY_15", INT_GLUT_BITMAP_9_BY_15);
        glutAddMenuEntry("BITMAP_TIMES_ROMAN_10 ", INT_GLUT_BITMAP_TIMES_ROMAN_10);
        glutAddMenuEntry("BITMAP_TIMES_ROMAN_24", INT_GLUT_BITMAP_TIMES_ROMAN_24);
        glutAddMenuEntry("BITMAP_HELVETICA_10 ", INT_GLUT_BITMAP_HELVETICA_10);
        glutAddMenuEntry("BITMAP_HELVETICA_12", INT_GLUT_BITMAP_HELVETICA_12);
        glutAddMenuEntry("BITMAP_HELVETICA_18", INT_GLUT_BITMAP_HELVETICA_18);
    
        fillMenu = glutCreateMenu(processFillMenu);
    
        glutAddMenuEntry("Fill", FILL);
        glutAddMenuEntry("Line", LINE);
    
        colorMenu = glutCreateMenu(processColorMenu);
        glutAddMenuEntry("Red", RED);
        glutAddMenuEntry("Blue", BLUE);
        glutAddMenuEntry("Green", GREEN);
        glutAddMenuEntry("Orange", ORANGE);
    
        mainMenu = glutCreateMenu(processMainMenu);
    
        glutAddSubMenu("Polygon Mode", fillMenu);
        glutAddSubMenu("Color", colorMenu);
        glutAddSubMenu("Font", fontMenu);
        // attach the menu to the right button
        glutAttachMenu(GLUT_RIGHT_BUTTON);
    
        // this will allow us to know if the menu is active
        glutMenuStatusFunc(processMenuStatus);
    }
    
    // -----------------------------------
    //             MAIN
    // -----------------------------------
    
    int main(int argc, char **argv)
    {
        glutInit(&argc, argv);
        glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
        glutInitWindowPosition(100, 100);
        glutInitWindowSize(320, 320);
        glutCreateWindow("Lighthouse3D - GLUT Tutorial");
    
        // register callbacks
        glutDisplayFunc(renderScene);
        glutReshapeFunc(changeSize);
        glutIdleFunc(renderScene);
    
        glutIgnoreKeyRepeat(1);
        glutKeyboardFunc(processNormalKeys);
        glutSpecialFunc(pressKey);
        glutSpecialUpFunc(releaseKey);
    
        // here are the two new functions
        glutMouseFunc(mouseButton);
        glutMotionFunc(mouseMove);
    
        // OpenGL init
        glEnable(GL_DEPTH_TEST);
        glEnable(GL_CULL_FACE);
    
        // init Menus
        createPopupMenus();
    
        // enter GLUT event processing cycle
        glutMainLoop();
    
        return 1;
    }

    显示效果如下

  • 相关阅读:
    C 语言 静态库和动态库的创建和应用
    C++ 中英文术语对照
    下午
    [转]内核 do_fork 函数源代码浅析
    关于C#反射机制,自己写的
    获取字符串中数字
    关于C#反射机制,来源于网络
    关于 Nhinernate 的one to one(转载)
    鼠标坐标的记录
    关于C#中hibernate.cfg.xml动态加载问题
  • 原文地址:https://www.cnblogs.com/flyinggod/p/12941407.html
Copyright © 2011-2022 走看看