Click here to Skip to main content
15,897,226 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 Microsoft.Samples.DirectX.UtilityToolkit;
using AGE_Engine3D.RenderObjects;
using AGE_Engine3D.Text;
using AGE_Engine3D.Math;
using Tao.OpenGl;

namespace AGE_Engine3D
{
    public class Profiler : IRenderOpenGL
    {
        #region Fields
        int NUM_PROFILE_SAMPLE = 50;
        ProfileSample[] Samples = null;
        ProfileSampleHistory[] History = null;
        double StartProfile = 0.0;
        double EndProfile = 0.0;
        double ElapsedTime = 0.0;
        List<string> ProfileText = null;
        bool _Isvisible = true;

        Matrix_44 _WorldMatrix = Matrix_44.Identity();
        public bool IsVisable { get { return _Isvisible; } }

        #endregion
        
        #region Methods

        public void ProfileInit(int NumberOfProfile)
        {
            this.NUM_PROFILE_SAMPLE = NumberOfProfile;
            Samples = new ProfileSample[NUM_PROFILE_SAMPLE];
            History = new ProfileSampleHistory[NUM_PROFILE_SAMPLE];
            for (int i = 0; i < NUM_PROFILE_SAMPLE; i++)
            {
                Samples[i].IsValid = false;
                History[i].IsValid = false;
            }
            this.StartProfile = DXTimer.GetTime();
        }

        public void ProfileStartTime()
        {
            this.StartProfile = DXTimer.GetTime();
        }

        public void ProfileBegin(string Name)
        {
            int i = 0;
            while (i < this.NUM_PROFILE_SAMPLE && Samples[i].IsValid)
            {
                if (this.Samples[i].Name == Name)
                {
                    this.Samples[i].OpenProfiles++;
                    this.Samples[i].ProfileInstance++;
                    this.Samples[i].StartTime = DXTimer.GetTime();
                    if (this.Samples[i].OpenProfiles > 1)
                        Console.WriteLine("Max 1 Open At Once");
                    return;
                }
                i++;
            }
            if (i >= this.NUM_PROFILE_SAMPLE)
            {
                Console.WriteLine("Exceeded Max Available Profile Samples");
                return;
            }
            this.Samples[i].Name = Name;
            this.Samples[i].IsValid = true;
            this.Samples[i].OpenProfiles = 1;
            this.Samples[i].ProfileInstance = 1;
            this.Samples[i].Accumulator = 0;
            this.Samples[i].StartTime = DXTimer.GetTime();
            this.Samples[i].ChildrenSampleTime = 0.0f;

        }

        public void ProfileEnd(string Name)
        {
            int i = 0;
            uint NumParents = 0;

            while (i < this.NUM_PROFILE_SAMPLE && Samples[i].IsValid == true)
            {
                if (Samples[i].Name == Name)
                {//Found the Sample
                    int inner = 0;
                    int parent = -1;
                    double EndTime = DXTimer.GetTime();
                    Samples[i].OpenProfiles--;

                    //Count the Parents and Find the Immediate Parent
                    while (this.Samples[inner].IsValid == true)
                    {
                        if (Samples[inner].OpenProfiles > 0)
                        {//Found a Parent
                            NumParents++;
                            if (parent < 0)
                            {
                                parent = inner;
                            }
                            else if (Samples[inner].StartTime >= Samples[parent].StartTime)
                            {//Replace Parent with a more immediate parent
                                parent = inner;
                            }
                        }
                        inner++;
                    }

                    //Remember the current number of parents of the sample
                    this.Samples[i].NumParents = NumParents;
                    if (parent >= 0)
                    {//Record this time in the ChildrenSampleTime
                        Samples[parent].ChildrenSampleTime += (EndTime - Samples[i].StartTime);
                    }

                    Samples[i].Accumulator += (EndTime - Samples[i].StartTime);
                    return;
                }
                i++;
            }

        }

        public void FinishProfile()
        {
            this.GetProfileData();
        }

        private void GetProfileData()
        {
            if (this.ProfileText == null) this.ProfileText = new List<string>();
            else this.ProfileText.Clear();
            List<string> result = this.ProfileText;
            int i = 0;
            this.EndProfile = DXTimer.GetTime();
            this.ElapsedTime = this.EndProfile - this.StartProfile;
            double InvDelta = 1 / (this.ElapsedTime);


            result.Add("  Ave |  Min |  Max |  # | Profile Name ");
            result.Add("---------------------------------------------------------------------");

            while (i < this.NUM_PROFILE_SAMPLE && Samples[i].IsValid)
            {
                double sampleTime, percentTime, AveTime, MinTime, MaxTime;

                if (this.Samples[i].OpenProfiles < 0)
                    Console.WriteLine("ProfileEnd() called Without a ProfileBegin()");
                else if (this.Samples[i].OpenProfiles > 0)
                    Console.WriteLine("ProfileBegin() called Without a ProfileEnd()");

                sampleTime = this.Samples[i].Accumulator - this.Samples[i].ChildrenSampleTime;
                percentTime = sampleTime * InvDelta * 100;
                AveTime = MinTime = MaxTime = percentTime;
                this.StoreProfileInHistory(this.Samples[i].Name, percentTime);
                this.GetProFileFromHistory(this.Samples[i].Name, ref AveTime, ref MinTime, ref MaxTime);

                String Output = AveTime.ToString(" #00.0 ") + "|" + MinTime.ToString(" #00.0 ") + "|" +
                                MaxTime.ToString(" #00.0 ") + "|" + Samples[i].ProfileInstance.ToString(" 00 ") + "|";

                for (int Indent = 0; Indent < Samples[i].NumParents; Indent++)
                {
                    Output = Output + "  ";
                }
                Output = Output + Samples[i].Name;

                result.Add(Output);

                i++;

            }
            for (i = 0; i < this.NUM_PROFILE_SAMPLE; i++)
            {
                Samples[i].IsValid = false;
            }
        }

        void StoreProfileInHistory(string Name, double percent)
        {
            int i = 0;
            double OldRatio;
            double NewRatio = 0.8 * this.ElapsedTime;
            if (NewRatio > 1)
                NewRatio = 1;
            OldRatio = 1 - NewRatio;

            while (i < this.NUM_PROFILE_SAMPLE && this.History[i].IsValid)
            {
                if (this.History[i].Name == Name)
                {
                    this.History[i].Ave = (this.History[i].Ave * this.History[i].NumCalc + percent) /
                                          (this.History[i].NumCalc + 1);
                    this.History[i].NumCalc++;
                    if (percent < this.History[i].Min)
                        this.History[i].Min = percent;

                    if (percent > this.History[i].MAx)
                        this.History[i].MAx = percent;

                    return;
                }

                i++;
            }
            if (i < this.NUM_PROFILE_SAMPLE)
            {
                this.History[i].Name = Name;
                this.History[i].IsValid = true;
                this.History[i].Ave = this.History[i].Min = this.History[i].MAx = percent;
            }
            else
                Console.WriteLine("Exceeded Max Available Profile Samples");
        }

        void GetProFileFromHistory(string Name, ref double Ave, ref double Min, ref double Max)
        {
            for (int i = 0; i < this.NUM_PROFILE_SAMPLE; i++)
            {
                if (this.History[i].IsValid && this.History[i].Name == Name)
                {
                    Ave = this.History[i].Ave;
                    Min = this.History[i].Min;
                    Max = this.History[i].MAx;
                    return;
                }
            }
            Ave = Min = Max = 0;
        }

        public void RenderOpenGL()
        {
            if (this.ProfileText != null)
            {
                if (this.ProfileText.Count > 0)
                {
                    IFont DefaultFont = ResourceManager.GetFont("Verdana");
                    float FontHieght = DefaultFont.CharHeight*1.25f;
                    if (DefaultFont != null)
                    {
                        #region Set the Model View Matrix
                        Gl.glMatrixMode(Gl.GL_MODELVIEW);
                        Gl.glLoadIdentity();
                        Gl.glTranslatef(0,SceneGraph.ScreenHeight, 0);
                        #endregion

                        Gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
                        Gl.glTranslatef(0, -13, 0);
                        Gl.glScalef(20, 20, 1);
                        foreach (string text in this.ProfileText)
                        {
                            DefaultFont.glPrint(text);
                            Gl.glTranslatef(0, -FontHieght, 0);
                        }
                        DefaultFont.glPrint("---------------------------------------------------------------------");
                        Gl.glTranslatef(0, -FontHieght, 0);
                        DefaultFont.glPrint("Frames Per Second :" + DXTimer.lastFrameRate);
                        Gl.glTranslatef(0, -FontHieght, 0);
                        double ElapsedTime = System.Math.Round(1000*DXTimer.GetElapsedTime(),1);
                        DefaultFont.glPrint("Elapsed Time (ms)  :" + ElapsedTime.ToString("####"));
                    }
                }
            }
        }

        #endregion
    }

    public struct ProfileSample
    {
        public bool IsValid;
        public uint ProfileInstance;
        public int OpenProfiles;

        public string Name;
        public double StartTime;
        public double Accumulator;
        public double ChildrenSampleTime;
        public uint NumParents;
    }

    public struct ProfileSampleHistory
    {
        public bool IsValid;
        public string Name;
        public double Ave;
        public double Min;
        public double MAx;
        public long NumCalc;
    }
}

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