WorldWind的渲染引擎

WorldWind中显示图像的是一个继承自Control的WorldWindow控件,代码:

public class WorldWindow : Control, IGlobe

 

初始化代码:

public WorldWindow()

{

     this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

     // The m_Device3d can't be created unless the control is at least 1 x 1 pixels in size

     this.Size = new Size(1,1); 

     try

     {

         if(!IsInDesignMode()) this.InitializeGraphics();

         ...... 

     }

     catch (InvalidCallException caught)

     {

         throw new InvalidCallException(

              "Unable to locate a compatible graphics adapter.", caught );

     }

     catch (NotAvailableException caught)

     {

         throw new NotAvailableException(

              "Unable to locate a compatible graphics adapter.", caught );

     }

}

初始化代码中主要的是:

(1) 设置窗体的样式:

    this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.Opaque, true);

(2) 初始化DirectX,具体的关于DirectX的初始化参见《WorldWind-Direct3D的初始化》

    if(!IsInDesignMode()) this.InitializeGraphics();

 

WorldWindow控件的 OnPaint() 方法:

protected override void OnPaint(PaintEventArgs e)

{

     try

     {

         if(m_Device3d==null)

         {

              e.Graphics.Clear(SystemColors.Control);

              return;

        

         Render();

         m_Device3d.Present();

     }

     catch(DeviceLostException)

     {

         try

         {

              AttemptRecovery();

              Render(); 

              m_Device3d.Present();

         }

         catch(DirectXException){ }

     }

}

从代码中可以看出,主要的渲染操作都存在于 Render() 方法中。

 

Render()方法:

public void Render()

    try

    {

        this.drawArgs.BeginRender();

 

        System.Drawing.Color backgroundColor = System.Drawing.Color.Black; 

        m_Device3d.Clear(ClearFlags.Target | ClearFlags.ZBuffer, backgroundColor, 1.0f, 0); 

        if (m_World == null)

        {

            m_Device3d.BeginScene();

            m_Device3d.EndScene();

            m_Device3d.Present();

            Thread.Sleep(25);

            return;

       

        // 用于对图像进行逻辑处理的线程

        if (m_WorkerThread == null)

        {

            m_WorkerThreadRunning = true;

            m_WorkerThread = new Thread(new ThreadStart(WorkerThreadFunc));

            m_WorkerThread.Name = "WorldWindow.WorkerThreadFunc";

            m_WorkerThread.IsBackground = true;

            if (World.Settings.UseBelowNormalPriorityUpdateThread)

            {

                m_WorkerThread.Priority = ThreadPriority.BelowNormal;

            }

            else

            {

                m_WorkerThread.Priority = ThreadPriority.Normal;

            }

            m_WorkerThread.Start();

       

        m_Device3d.BeginScene();

 

        // 渲染当前星球,这是主要的渲染过程

        m_World.Render(this.drawArgs); 

        // 渲染位置信息

        RenderPositionInfo(); 

        // 渲染菜单栏

        _menuBar.Render(drawArgs);

        m_FpsGraph.Render(drawArgs);   

        // 渲染屏幕消息    

        if (m_World.OnScreenMessages != null)

        {

            try

            {

                foreach (OnScreenMessage dm in m_World.OnScreenMessages)

                {

                    int xPos = (int)Math.Round(dm.X * this.Width);

                    int yPos = (int)Math.Round(dm.Y * this.Height);

                    Rectangle posRect = new Rectangle(xPos, yPos, this.Width, this.Height);

                    this.drawArgs.defaultDrawingFont.DrawText(null,

                        dm.Message, posRect,

                        DrawTextFormat.NoClip | DrawTextFormat.WordBreak,

                        Color.White);

                }

            }

            catch (Exception){}

       

        m_Device3d.EndScene();

    }

    catch (Exception ex){ Log.Write(ex);}

    finallythis.drawArgs.EndRender();}

    drawArgs.UpdateMouseCursor(this);

}

 

图像逻辑处理线程方法:

private void WorkerThreadFunc()

{

     const int refreshIntervalMs = 150; // 更新频率:Max 6 updates per second

     while(m_WorkerThreadRunning)

     {

         try

        

              long startTicks = 0;

              PerformanceTimer.QueryPerformanceCounter(ref startTicks);

 

              m_World.Update(this.drawArgs);

 

              long endTicks = 0;

              PerformanceTimer.QueryPerformanceCounter(ref endTicks);

 

              float elapsedMilliSeconds = 1000*(float)(endTicks - startTicks)/PerformanceTimer.TicksPerSecond;

              float remaining = refreshIntervalMs - elapsedMilliSeconds;

              if(remaining > 0) Thread.Sleep((int)remaining);

         }

         catch(Exception caught){ Log.Write(caught);}

     }

}

 

WorldWind渲染循环:

/// <summary>

/// The world render loop. Borrowed from FlightGear and Tom Miller's blog

/// </summary>

public void OnApplicationIdle(object sender, EventArgs e)

{

     // Sleep will always overshoot by a bit so under-sleep by 2ms in the hopes of never oversleeping.

     const float SleepOverHeadSeconds = 2e-3f;

     // Overhead associated with displaying the frame

     const float PresentOverheadSeconds = 0;//3e-4f;

     try

     {

         if (Parent.Focused && !Focused) Focus(); 

         while (IsAppStillIdle)

        

              Render(); 

              if (World.Settings.ThrottleFpsHz > 0)

              {

                   // optionally throttle the frame rate (to get consistent frame rates or reduce CPU usage.

                   float frameSeconds = 1.0f / World.Settings.ThrottleFpsHz - PresentOverheadSeconds;

                   // Sleep for remaining period of time until next render

                   float sleepSeconds = frameSeconds - SleepOverHeadSeconds - DrawArgs.SecondsSinceLastFrame;

                   if(sleepSeconds > 0)

                   {

                       // Don't sleep too long. We don't know the accuracy of Thread.Sleep

                       Thread.Sleep((int) (1000 * sleepSeconds));

                       // Burn off what little time still remains at 100% CPU load

                       while(DrawArgs.SecondsSinceLastFrame < frameSeconds)

                       {

                            // Patience

                       }

                   }

              }

              drawArgs.Present();

         }

     }

     catch(DeviceLostException){ AttemptRecovery();}

     catch(Exception caught){ Log.Write(caught);}

}

 

IsAppStillIdle属性 

/// <summary>

/// Determine whether any window messages is queued.

/// </summary>

private static bool IsAppStillIdle

{

     get

     {

         NativeMethods.Message msg;

         return !NativeMethods.PeekMessage(out msg, IntPtr.Zero, 0, 0, 0);

     }

 

 

WorldWind的渲染循环是在 Application Idle 时进行的:

Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);

MainApplication app = new MainApplication();

Application.Idle += new EventHandler(app.WorldWindow.OnApplicationIdle);

Application.Run(app);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值