博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[WorldWind学习]11.TerrainViewer插件和双线程
阅读量:6811 次
发布时间:2019-06-26

本文共 14420 字,大约阅读时间需要 48 分钟。

 TerrainViewer的入口Main()函数:

View Code
1  static void Main(string[] args) 2  { 3             using (Viewer viewer = new Viewer()) 4               { 5                  viewer.ProcessArgs(args);        // Read command line args 6                  viewer.InitializeDevice();        // Direct 3D device setup 7                 viewer.InitializeKeyboard();    // Keyboard setup 8                  viewer.InitializeMapList();        // Create Map menu 9                  viewer.InitializeVerticalFactorMenu(); // Create vertical factor menu10                 viewer.InitializeTexturesMenu();// Create Textures menu11                  viewer.InitializeSidesMenu();    // Create Sides menu12                  viewer.InitializeSkyMenu();        // Create Sky menu13                  viewer.MapMenuSelectMap(0);        // Load first map14                  viewer.Show();15                  Application.Run(viewer);        // Run16              }17 }

初始化设备:InitializeDevice()

鼠标交互的基本原理:

根据地图位置(参数dist)设置相机,之后相机位置保持不变。滚轮操作和键盘操作更改dist,修改相机位置。

如下为处理键盘操作的部分代码。

1 // Change Distance 2 if (keys[Key.NumPadPlus] && !shift && !ctrl)     3       { 4     dist -= dist * 0.02f; 5     redraw = true; 6       } 7 if (keys[Key.NumPadMinus] && !shift && !ctrl) 8       { 9     dist += dist * 0.02f;10     redraw = true;11       }

查看重载的OnPaint函数,在OnPaint中调用了CameraViewSetup()方法。

1 // Camera setup2   private void CameraViewSetup()3   {4       float aspectRatio =  (float)device.Viewport.Width / device.Viewport.Height;5       device.Transform.Projection = Matrix.PerspectiveFovLH(fov, aspectRatio, mapWidth == 0 ? 15f : (float)(mapWidth / 10), mapWidth == 0 ? 5000f : (float)(mapWidth * 3));6       device.Transform.View = Matrix.LookAtLH(new Vector3(0,0,dist), new Vector3(0,0,0), new Vector3(1,0,0));7   }

鼠标左键点击拖动,移动地图,更改了参数dx和dy。

鼠标右键点击拖动,旋转地图,更改了参数angle和angle2

1 protected override void OnMouseMove(MouseEventArgs e) 2         { 3             if(mouseDownStartPosition == Point.Empty) 4                 return; 5             // Mouse drag 6             bool isMouseLeftButtonDown = ((int)e.Button & (int)MouseButtons.Left) != 0; 7             bool isMouseRightButtonDown = ((int)e.Button & (int)MouseButtons.Right) != 0; 8             double dxMouse = this.mouseDownStartPosition.X - e.X; 9             double dyMouse = this.mouseDownStartPosition.Y - e.Y;10             if(isMouseLeftButtonDown && !isMouseRightButtonDown) 11             {12                 // Move map13                 double moveFactor = dist * 0.001f;14                 dx = mouseDownStartDx - (float)(Math.Sin(angle) * dxMouse * moveFactor) + (float)(Math.Cos(angle) * dyMouse * moveFactor);15                 dy = mouseDownStartDy - (float)(Math.Cos(angle) * dxMouse * moveFactor) - (float)(Math.Sin(angle) * dyMouse * moveFactor);16                 redraw = true;17             }18             if(isMouseRightButtonDown && !isMouseLeftButtonDown) 19             {20                 // Rotate map21                 double spinFactor = 0.003f;22                 angle = mouseDownStartAngle + (float)(dxMouse * spinFactor * rightClickFactor);23                 angle2 = mouseDownStartAngle2 + (float)(dyMouse * spinFactor * rightClickFactor);24                 redraw = true;25             }26             if(isMouseRightButtonDown && isMouseLeftButtonDown) 27             {28                 // Rotate light29                 double spinFactor = 0.003f;30                 lightHeading = mouseDownLightAngle + (float)(dxMouse * spinFactor);31                 lightElevation = mouseDownLightAngle2 + (float)(dyMouse * spinFactor);32                 redraw = true;33             }34         }

在OnPaint函数中调用了如下代码。

1 // Translation and Orientation angle / angle22 if(angle2 < 0) angle2 = 0;3 if(angle2 > Math.PI / 2) angle2 = (float)(Math.PI / 2);4 device.Transform.World = Matrix.Translation(dx, dy, dz);5 device.Transform.World *= Matrix.RotationZ(angle);6 device.Transform.World *= Matrix.RotationY(angle2);

改变世界坐标矩阵,实现平移和旋转。

这个插件和WW鼠标操作的机制很像,感觉游戏或者三维就是不断地修改参数(变量为某一限定域所有),然后重新渲染场景。

不过游戏是以第一人称观察(第三人称相机)(相机在动),物体位置不动,所以有身临其境的感觉;而这个插件的基本模式则是改变模型,是物体在动(相机不动)。还是有些区别的。

当然这个插件和ArcScene也可以改变相机,不过不是基本的。

此插件通过不断触发OnPaint事件来更改场景,WW通过Idle()来更改场景?

WW是双线程的?这个再理解一下。

MainApplication方法调用worldWindow.Render();方法,即主线程负责渲染。

WorldWindow的Render()方法启动了一个名为WorldWindow.WorkerThreadFunc线程。

1 public void Render()  2         {  3             long startTicks = 0;  4             PerformanceTimer.QueryPerformanceCounter(ref startTicks);  5   6             try  7             {  8                 this.drawArgs.BeginRender();  9  10                 // Render the sky according to view - example, close to earth, render sky blue, render space as black 11                 System.Drawing.Color backgroundColor = System.Drawing.Color.Black; 12  13                 /*if(drawArgs.WorldCamera != null &&  14                     drawArgs.WorldCamera.Altitude < 1000000f && 15                     m_World != null && 16                     m_World.Name.IndexOf("Earth") >= 0) 17                 { 18                     float percent = 1 - (float)(drawArgs.WorldCamera.Altitude / 1000000); 19                     if(percent > 1.0f) 20                         percent = 1.0f; 21                     else if(percent < 0.0f) 22                         percent = 0.0f; 23  24                     backgroundColor = System.Drawing.Color.FromArgb( 25                         (int)(World.Settings.SkyColor.R*percent), 26                         (int)(World.Settings.SkyColor.G*percent), 27                         (int)(World.Settings.SkyColor.B*percent)); 28                 }*/ 29  30                 m_Device3d.Clear(ClearFlags.Target | ClearFlags.ZBuffer, backgroundColor, 1.0f, 0); 31  32                 if (m_World == null) 33                 { 34                     m_Device3d.BeginScene(); 35                     m_Device3d.EndScene(); 36                     m_Device3d.Present(); 37                     Thread.Sleep(25); 38                     return; 39                 } 40  41                 if (m_WorkerThread == null) 42                 { 43                     m_WorkerThreadRunning = true; 44                     m_WorkerThread = new Thread(new ThreadStart(WorkerThreadFunc)); 45                     m_WorkerThread.Name = "WorldWindow.WorkerThreadFunc"; 46                     m_WorkerThread.IsBackground = true; 47                     if (World.Settings.UseBelowNormalPriorityUpdateThread) 48                     { 49                         m_WorkerThread.Priority = ThreadPriority.BelowNormal; 50                     } 51                     else 52                     { 53                         m_WorkerThread.Priority = ThreadPriority.Normal; 54                     } 55                     // BelowNormal makes rendering smooth, but on slower machines updates become slow or stops 56                     // TODO: Implement dynamic FPS limiter (or different solution) 57                     m_WorkerThread.Start();//启动后台线程 58                 } 59  60                 this.drawArgs.WorldCamera.Update(m_Device3d);//更新相机 61  62                 m_Device3d.BeginScene(); 63  64                 // Set fill mode 65                 if (renderWireFrame) 66                     m_Device3d.RenderState.FillMode = FillMode.WireFrame; 67                 else 68                     m_Device3d.RenderState.FillMode = FillMode.Solid; 69  70                 drawArgs.RenderWireFrame = renderWireFrame; 71  72                 // Render the current planet 73                 m_World.Render(this.drawArgs);//渲染地球 74  75                 if (World.Settings.ShowCrosshairs) 76                     this.DrawCrossHairs(); 77  78                 frameCounter++; 79                 if (frameCounter == 30) 80                 { 81                     fps = frameCounter / (float)(DrawArgs.CurrentFrameStartTicks - lastFpsUpdateTime) * PerformanceTimer.TicksPerSecond; 82                     frameCounter = 0; 83                     lastFpsUpdateTime = DrawArgs.CurrentFrameStartTicks; 84                 } 85  86                 m_RootWidget.Render(drawArgs);//渲染部件 87                 m_NewRootWidget.Render(drawArgs); 88  89                 if (saveScreenShotFilePath != null) 90                     SaveScreenShot(); 91  92                 drawArgs.device.RenderState.ZBufferEnable = false; 93  94                 // 3D rendering complete, switch to 2D for UI rendering 95  96                 // Restore normal fill mode 97                 if (renderWireFrame) 98                     m_Device3d.RenderState.FillMode = FillMode.Solid; 99 100                 // Disable fog for UI101                 m_Device3d.RenderState.FogEnable = false;102 103                 /*104                                 if(World.Settings.ShowDownloadIndicator)105                                 {106                                     if(m_downloadIndicator == null)107                                         m_downloadIndicator = new DownloadIndicator();108                                     m_downloadIndicator.Render(drawArgs);109                                 }110                 */111                 RenderPositionInfo();112 113                 _menuBar.Render(drawArgs);114                 m_FpsGraph.Render(drawArgs);115                 116                 if (m_World.OnScreenMessages != null)117                 {118                     try119                     {120                         foreach (OnScreenMessage dm in m_World.OnScreenMessages)121                         {122                             int xPos = (int)Math.Round(dm.X * this.Width);123                             int yPos = (int)Math.Round(dm.Y * this.Height);124                             Rectangle posRect =125                                 new Rectangle(xPos, yPos, this.Width, this.Height);126                             this.drawArgs.defaultDrawingFont.DrawText(null,127                                 dm.Message, posRect,128                                 DrawTextFormat.NoClip | DrawTextFormat.WordBreak,129                                 Color.White);130                         }131                     }132                     catch (Exception)133                     {134                         // Don't let a script error cancel the frame.135                     }136                 }137 138                 m_Device3d.EndScene();139             }140             catch (Exception ex)141             {142                 Log.Write(ex);143             }144             finally145             {146                 147                 if(World.Settings.ShowFpsGraph)148                 {149                     long endTicks = 0;150                     PerformanceTimer.QueryPerformanceCounter(ref endTicks);151                     float elapsedMilliSeconds = 1000.0f / (1000.0f*(float)(endTicks - startTicks)/PerformanceTimer.TicksPerSecond);152                     m_FrameTimes.Add(elapsedMilliSeconds);153                 }154                 this.drawArgs.EndRender();155             }156             drawArgs.UpdateMouseCursor(this);157         }

启动后台线程后调用异步方法WorkerThreadFunc()

1 ///  2         /// Background worker thread loop (updates UI) 3         ///  4         private void WorkerThreadFunc() 5         { 6             const int refreshIntervalMs = 150; // Max 6 updates per seconds 7             while(m_WorkerThreadRunning) 8             { 9                 try10                 {11                     if(World.Settings.UseBelowNormalPriorityUpdateThread && m_WorkerThread.Priority == System.Threading.ThreadPriority.Normal)12                     {13                         m_WorkerThread.Priority = System.Threading.ThreadPriority.BelowNormal;14                     }15                     else if(!World.Settings.UseBelowNormalPriorityUpdateThread && m_WorkerThread.Priority == System.Threading.ThreadPriority.BelowNormal)16                     {17                         m_WorkerThread.Priority = System.Threading.ThreadPriority.Normal;18                     }19 20                     long startTicks = 0;21                     PerformanceTimer.QueryPerformanceCounter(ref startTicks);22 23                     m_World.Update(this.drawArgs);//更新世界对象24 25                     long endTicks = 0;26                     PerformanceTimer.QueryPerformanceCounter(ref endTicks);27                     float elapsedMilliSeconds = 1000*(float)(endTicks - startTicks)/PerformanceTimer.TicksPerSecond;28                     float remaining = refreshIntervalMs - elapsedMilliSeconds;29                     if(remaining > 0)30                         Thread.Sleep((int)remaining);31                 }32                 catch(Exception caught)33                 {34                     Log.Write(caught);35                 }36             }37         }

World的Update方法:

Update
1  public override void Update(DrawArgs drawArgs) 2         { 3             if (!this.isInitialized) 4             { 5                 this.Initialize(drawArgs); 6             } 7  8             if (this.RenderableObjects != null) 9             {10                 this.RenderableObjects.Update(drawArgs);11             }12             if (this.m_WorldSurfaceRenderer != null)13             {14                 this.m_WorldSurfaceRenderer.Update(drawArgs);15             }16 17             if (this.m_projectedVectorRenderer != null)18             {19                 this.m_projectedVectorRenderer.Update(drawArgs);20             }21 22             if (this.TerrainAccessor != null)23             {24                 if (drawArgs.WorldCamera.Altitude < 300000)25                 {26                     if (System.DateTime.Now - this.lastElevationUpdate > TimeSpan.FromMilliseconds(500))27                     {28                         drawArgs.WorldCamera.TerrainElevation = (short)this.TerrainAccessor.GetElevationAt(drawArgs.WorldCamera.Latitude.Degrees, drawArgs.WorldCamera.Longitude.Degrees, 100.0 / drawArgs.WorldCamera.ViewRange.Degrees);29                         this.lastElevationUpdate = System.DateTime.Now;30                     }31                 }32                 else33                     drawArgs.WorldCamera.TerrainElevation = 0;34             }35             else36             {37                 drawArgs.WorldCamera.TerrainElevation = 0;38             }39 40             if (World.Settings.EnableAtmosphericScattering && m_outerSphere != null)41                 m_outerSphere.Update(drawArgs);42         }

 

转载地址:http://dswzl.baihongyu.com/

你可能感兴趣的文章
SQL修改字段默认值
查看>>
像素和dip之间的相互转换
查看>>
关于”数据库连接串中的 |DataDirectory|”
查看>>
Android Read-only file system 错误 /sdcard问题
查看>>
Beep Driver
查看>>
Perl包和模块
查看>>
Apache Mahout 简介
查看>>
正试图在 os 加载程序锁内执行托管代码
查看>>
Web站点风格切换的实现
查看>>
在 SQLite3 中使用回调函数
查看>>
POJ 数学(2)
查看>>
C#中HashTable的用法
查看>>
数据库原理 知识点总结
查看>>
Java:IO流之字符流Reader、Writer详解
查看>>
Windows2003服务器安全配置:先关闭不需要的端口(转自)
查看>>
HDU1247 Hat’s Words 【trie树】
查看>>
iOS开发--动画篇之layout动画深入
查看>>
nullpointerxception——处理思路
查看>>
使用 jsPlumb 绘制拓扑图 —— 异步载入与绘制的实现
查看>>
vue - 组件基础
查看>>