Click here to Skip to main content
15,896,489 members
Articles / Multimedia / OpenGL

Creating a Window - Building a 3D Engine

Rate me:
Please Sign up or sign in to vote.
3.67/5 (4 votes)
7 Feb 2009CPOL4 min read 50.5K   2K   35  
This article describes the creation of an OpenGL window or OpenGL control with C# and Tao Framework
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Tao.OpenGl;
using Tao.Platform.Windows;

namespace AGE_Engine3D.Text
{
    public class OutLineTypeFont:IFont
    {
        #region Fields
        string _FontName = "";
        int FontBasePtr = -1;
        Gdi.GLYPHMETRICSFLOAT[] gmf = null;
        FontAlign _Alignment = FontAlign.LEFT;
        float MaxHieght = 0;
        private bool disposed = false;
        #endregion
        #region Interfaces
        public string FontName
        { get { return this._FontName; } }
        public FontAlign Alignment
        {
            get { return this._Alignment; }
            set { this._Alignment = value; }
        }
        public float CharHeight
        {
            get { return this.MaxHieght; }
        }
        #endregion
        #region Methods
        public bool BuildFont(IntPtr hDC, string FontTypeName, int Height, int Width, int AngleOfEscapement,
                              int OrientationAngle, int FontWieght, bool IsItalic, bool IsUnderline, bool IsStrikeout)
        {
            bool result = false;

            this._FontName = FontTypeName;

            IntPtr FontPtr = IntPtr.Zero;
            FontBasePtr = Gl.glGenLists(256);                                       // Storage For 256 Characters
            this.gmf = new Gdi.GLYPHMETRICSFLOAT[256];
            try
            {
                FontPtr = Gdi.CreateFont(                                           // Create The Font
                    -Height,                                                        // Height Of Font
                    Width,                                                          // Width Of Font
                    AngleOfEscapement,                                              // Angle Of Escapement
                    OrientationAngle,                                               // Orientation Angle
                    FontWieght,                                                     // Font Weight
                    IsItalic,                                                       // Italic
                    IsStrikeout,                                                    // Underline
                    IsUnderline,                                                    // Strikeout
                    Gdi.ANSI_CHARSET,                                               // Character Set Identifier
                    Gdi.OUT_TT_PRECIS,                                              // Output Precision
                    Gdi.CLIP_DEFAULT_PRECIS,                                        // Clipping Precision
                    Gdi.ANTIALIASED_QUALITY,                                        // Output Quality
                    Gdi.FF_DONTCARE | Gdi.DEFAULT_PITCH,                            // Family And Pitch
                    FontName);                                                      // Font Name

                Gdi.SelectObject(hDC, FontPtr);                                        // Selects The Font We Created

                result = Wgl.wglUseFontOutlinesA(
                    hDC,                                                            // Select The Current DC
                    0,                                                              // Starting Character
                    255,                                                            // Number Of Display Lists To Build
                    FontBasePtr,                                                    // Starting Display Lists
                    0,                                                              // Deviation From The True Outlines
                    0.2f,                                                           // Font Thickness In The Z Direction
                    Wgl.WGL_FONT_POLYGONS,                                          // Use Polygons, Not Lines
                    this.gmf);
                foreach (Gdi.GLYPHMETRICSFLOAT tmp in this.gmf)
                    if (tmp.gmfBlackBoxY > this.MaxHieght)
                        this.MaxHieght = tmp.gmfBlackBoxY;
            }
            catch
            {
                if (this.FontBasePtr != -1)
                {
                    Gl.glDeleteLists(this.FontBasePtr, 256);
                }
            }
            finally
            {
                if (FontPtr != IntPtr.Zero)
                {
                    Gdi.DeleteObject(FontPtr);
                }
            }
            return result;
        }

        public void KillFont()
        {
            Gl.glDeleteLists(FontBasePtr, 256);                                    // Delete All 256 Characters
        }

        public void glPrint(string text)
        {
            float TextOffset = 0;
            Gl.glPushMatrix();
            #region Deal with the Text alignment
            if (this._Alignment != FontAlign.LEFT)
            {
                for (int loop = 0; loop < text.Length; loop++)
                {                     // Loop To Find Text Length
                    TextOffset += gmf[text[loop]].gmfCellIncX;                         // Increase Length By Each Characters Width
                }
                if (this._Alignment == FontAlign.RIGHT)
                {
                    Gl.glTranslatef(-TextOffset, 0, 0);
                }
                if (this._Alignment == FontAlign.CENTERED)
                {
                    Gl.glTranslatef(-TextOffset / 2, 0, 0);
                }
            } 
            #endregion
            Gl.glPushAttrib(Gl.GL_LIST_BIT);                                    // Pushes The Display List Bits
            Gl.glListBase(this.FontBasePtr);                                            // Sets The Base Character to 0
            byte[] textbytes = new byte[text.Length];
            for (int i = 0; i < text.Length; i++) textbytes[i] = (byte)text[i];
            Gl.glCallLists(text.Length, Gl.GL_UNSIGNED_BYTE, textbytes);        // Draws The Display List Text
            Gl.glPopAttrib();                                                   // Pops The Display List Bits
            Gl.glPopMatrix();
        }
        public float GetStringLength(string text)
        {
            #region Short Circuit Null Strings and Zero length Strings
            if (text == null)
                return 0;
            if (text.Length == 0)
                return 0; 
            #endregion

            float result = 0;

            for (int loop = 0; loop < text.Length; loop++)
            {                     // Loop To Find Text Length
                result += gmf[text[loop]].gmfCellIncX;                         // Increase Length By Each Characters Width
            }
            return result;
        }

        public void Dispose()
        {
            Dispose(true);
            // This object will be cleaned up by the Dispose method.
            // Therefore, you should call GC.SupressFinalize to
            // take this object off the finalization queue
            // and prevent finalization code for this object
            // from executing a second time.
            GC.SuppressFinalize(this);
        }

        private void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                    // Dispose managed resources.
                    gmf = null;
                }

                // Call the appropriate methods to clean up
                // unmanaged resources here.
                Gl.glDeleteLists(this.FontBasePtr, 256);

                // Note disposing has been done.
                disposed = true;

            }
        }



        #endregion


    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Engineer Lea+Elliott, Inc.
United States United States
I am a licensed Electrical Engineer at Lea+Elliott, Inc. We specialize in the planning, procurement and implementation of transportation systems, with special emphasis on automated and emerging technologies.

Comments and Discussions