欢迎来到千学网!
您现在的位置:首页 > 实用文 > 其他范文

WorldWind系列五:插件加载过程全解析

时间:2023-02-21 08:09:20 其他范文 收藏本文 下载本文

以下是小编整理的WorldWind系列五:插件加载过程全解析,本文共2篇,欢迎阅读分享,希望对您有所帮助。

WorldWind系列五:插件加载过程全解析

篇1:WorldWind系列五:插件加载过程全解析

不得不承认World Wind的代码真的很庞大,没有太多帮助文档的前提下,一头钻进代码里肯定令你头疼的,甚至研究代码间关联仿佛是在走迷宫,我最近一直想弄明白如何在 MenuBar中加载那些插件的,WorldWind学习系列四中研究的只是特殊的三个功能加载的,那三个没有继承Plugin类,不算是插件功能加载。所以WorldWind学习系列四加载的三个是特殊情况,不是一般的插件加载。今天下午终于柳暗花明,如果你真正关注World Wind分析,那么就好好看看下面的插件加载过程全解析。

我们先看看Plugin类的继承图,看看到底都有些什么插件,然后在分析一般性的插件加载全过程。

哦,原来这么多插件,我们要基于WW开发自己的应用,只需继承Plugin类写出自己的插件功能即可的。

我们现在分析插件加载过程,请确保你看过WorldWind学习系列二:擒贼先擒王篇2 中的(5.加载上次使用的配置信息)。加载的插件入口就是WorldWind.cs的Main中调用的LoadSettings()静态方法。

1.读取WorldWind的配置中插件信息

加载WorldWind配置

private static void LoadSettings()

{

try

{

//先读取上次使用时保存的“使用插件配置文件”,如果存在,则从文件中读取配置实例化WorldWindSettings

Settings = (WorldWindSettings) SettingsBase.Load(Settings, SettingsBase.LocationType.User);

if(!File.Exists(Settings.FileName))

{

//我们假定是配置文件不存在,这就是一个个地加载插件,保存到ArrayList中

Settings.PluginsLoadedOnStartup.Add(“ShapeFileInfoTool”);

//Settings.PluginsLoadedOnStartup.Add(“OverviewFormLoader”);

//Settings.PluginsLoadedOnStartup.Add(“Atmosphere”);

Settings.PluginsLoadedOnStartup.Add(“SkyGradient”);

Settings.PluginsLoadedOnStartup.Add(“BmngLoader”);

//Settings.PluginsLoadedOnStartup.Add(“Compass”);

//Settings.PluginsLoadedOnStartup.Add(“ExternalLayerManagerLoader”);

Settings.PluginsLoadedOnStartup.Add(“MeasureTool”);

//Settings.PluginsLoadedOnStartup.Add(“MovieRecorder”);

Settings.PluginsLoadedOnStartup.Add(“NRLWeatherLoader”);

Settings.PluginsLoadedOnStartup.Add(“ShapeFileLoader”);

Settings.PluginsLoadedOnStartup.Add(“Stars3D”);

Settings.PluginsLoadedOnStartup.Add(“GlobalClouds”);

Settings.PluginsLoadedOnStartup.Add(“PlaceFinderLoader”);

Settings.PluginsLoadedOnStartup.Add(“LightController”);

Settings.PluginsLoadedOnStartup.Add(“Earthquake_2.0.2.1”);

Settings.PluginsLoadedOnStartup.Add(“Historical_Earthquake_2.0.2.2”);

Settings.PluginsLoadedOnStartup.Add(“KMLImporter”);

//Settings.PluginsLoadedOnStartup.Add(“doublezoom”);

//Settings.PluginsLoadedOnStartup.Add(“PlanetaryRings”);

Settings.PluginsLoadedOnStartup.Add(“TimeController”);

//Settings.PluginsLoadedOnStartup.Add(“WavingFlags”);

Settings.PluginsLoadedOnStartup.Add(“ScaleBarLegend”);

Settings.PluginsLoadedOnStartup.Add(“Compass3D”);

Settings.PluginsLoadedOnStartup.Add(“AnaglyphStereo”);

Settings.PluginsLoadedOnStartup.Add(“GlobeIcon”);

}

// decrypt encoded user credentials

DataProtector dp = new DataProtector(DataProtector.Store.USE_USER_STORE);

if(Settings.ProxyUsername.Length >0) Settings.ProxyUsername = dp.TransparentDecrypt(Settings.ProxyUsername);

if(Settings.ProxyPassword.Length >0) Settings.ProxyPassword = dp.TransparentDecrypt(Settings.ProxyPassword);

}

catch(Exception caught)

{

Log.Write(caught);

}

}

2.Main()中后面调用MainApplication()方法,该MainApplication()调用 OpenStartupWorld(),用来初始化启动World对象。OpenStartupWorld()方法首先确定加载的是Earth/Moon 等,然后开始加载一个星球。

加载一个星球代码

///

/// Loads a new planet

///

private void OpenWorld(string worldXmlFile)

{

if(this.worldWindow.CurrentWorld != null)

{

try

{

this.worldWindow.ResetToolbar();

}

catch

{}

try

{

foreach(PluginInfo p in this.compiler.Plugins)

{

try

{

if(p.Plugin.IsLoaded)

p.Plugin.Unload();

}

catch

{}

}

}

catch

{}

try

{

this.worldWindow.CurrentWorld.Dispose();

}

catch

{}

}

if(this.gotoDialog != null)

{

this.gotoDialog.Dispose();

this.gotoDialog = null;

}

if(this.rapidFireModisManager != null)

{

this.rapidFireModisManager.Dispose();

this.rapidFireModisManager = null;

}

if(this.animatedEarthMananger != null)

{

this.animatedEarthMananger.Dispose();

this.animatedEarthMananger = null;

}

if(this.wmsBrowser != null)

{

this.wmsBrowser.Dispose();

this.wmsBrowser = null;

}

worldWindow.CurrentWorld = WorldWind.ConfigurationLoader.Load(worldXmlFile, worldWindow.Cache);

this.splashScreen.SetText(“Initializing menus...”);

// InitializePluginCompiler()是我们要关注的初始化插件编辑器PluginCompiler(真正管理加载插件的类)

InitializePluginCompiler();

//RenderableObject系统很复杂,我们稍后准备专门分析一下

foreach(RenderableObject worldRootObject in this.worldWindow.CurrentWorld.RenderableObjects.ChildObjects)

{

this.AddLayerMenuButtons(this.worldWindow, worldRootObject);

}

//加载Earth专有的MenuButton( AnimatedEarthManager和RapidFireModisManager)的配置,

//这里主要不关注

this.AddInternalPluginMenuButtons();

this.menuItemModisHotSpots.Enabled = worldWindow.CurrentWorld.IsEarth;

this.menuItemAnimatedEarth.Enabled = worldWindow.CurrentWorld.IsEarth;

}

3.我们看看InitializePluginCompiler()如何加载插件的?

初始化PluginCompiler

///

/// Compile and run plug-in “scripts”

///

private void InitializePluginCompiler()

{

Log.Write(Log.Levels.Debug, “CONF”, “initializing plugin compiler...”);

this.splashScreen.SetText(“Initializing plugins...”);

string pluginRoot = Path.Combine(DirectoryPath, “Plugins”);

compiler = new PluginCompiler(this, pluginRoot);

//#if DEBUG

// Search for plugins in worldwind.exe (plugin development/debugging aid)

compiler.FindPlugins(Assembly.GetExecutingAssembly());

//#endif

//从启动文件夹下Plugins文件夹,加载插件

compiler.FindPlugins();

//加载启动插件插件

compiler.LoadStartupPlugins();

}

4.加载启动插件函数的代码

加载启动插件

/// Loads the plugins that are set for load on world wind startup.

///

public void LoadStartupPlugins()

{

foreach(PluginInfo pi in m_plugins)

{

if(pi.IsLoadedAtStartup)

{

try

{

// Compile

Log.Write(Log.Levels.Debug, LogCategory, “loading ”+pi.Name+“ ...”);

worldWind.SplashScreen.SetText(“Initializing plugin ” + pi.Name);

//Load方法加载插件,Plugin类的Load()为虚方法,实质上调用的是各个插件重载后的Load()方法

Load(pi);

}

catch(Exception caught)

{

// Plugin failed to load

string message = “Plugin ” + pi.Name + “ failed: ” + caught.Message;

Log.Write(Log.Levels.Error, LogCategory, message);

Log.Write(caught);

// Disable automatic load of this plugin on startup

pi.IsLoadedAtStartup = false;

worldWind.SplashScreen.SetError(message);

}

}

}

}

5.现在看两个插件类重载的Load()方法的实例。例如:Compass3D.cs和TimeController.cs。

Compass3D.cs的Load()方法

重载后的Load方法

public override void Load()

{

m_menuItem = new System.Windows.Forms.MenuItem(“Compass”);

m_menuItem.Click += new EventHandler(m_menuItem_Click);

m_menuItem.Checked = World.Settings.ShowCompass;

ParentApplication.ToolsMenu.MenuItems.Add(m_menuItem);

m_form. = new FormWidget(“Compass”);

m_form.ClientSize = new System.Drawing.Size(200, 200);

m_form.Location = new System.Drawing.Point(0, 400);

m_form.BackgroundColor = World.Settings.WidgetBackgroundColor;

m_form.AutoHideHeader = true;

m_form.VerticalScrollbarEnabled = false;

m_form.HorizontalScrollbarEnabled = false;

m_form.BorderEnabled = false;

//注册两个窗体事件

m_form.OnResizeEvent += new FormWidget.ResizeHandler(m_form_OnResizeEvent);

m_form.OnVisibleChanged += new VisibleChangedHandler(m_form_OnVisibleChanged);

//实例化Compass3DWidget

m_compass = new Compass3DWidget();

m_compass.Location = new System.Drawing.Point(5, 0);

m_compass.Font = new System.Drawing.Font(“Ariel”, 10.0f, System.Drawing.FontStyle.Bold);

m_compass.ParentWidget = m_form;

m_form_OnResizeEvent(m_form, m_form.WidgetSize);

m_form.ChildWidgets.Add(m_compass);

m_form.Visible = World.Settings.ShowCompass;

//将要绘制的Widget加载到DrawArgs.NewRootWidget.ChildWidgets,为了在WorldWindow.cs的Render()方法里渲染

DrawArgs.NewRootWidget.ChildWidgets.Add(m_form);

//Compass 3D工具菜单按钮

m_toolbarItem = new WorldWind.NewWidgets.WidgetMenuButton(

“Compass 3D”,

basePath + “\\Data\\Icons\\Interface\\compass2.png”,

m_form);

//向MenuBar中添加Compass 3D菜单按钮

ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_toolbarItem);

base.Load();

}

TimeController.cs的Load方法,如下:

时间控制

public override void Load()

{

try

{

m_window = new WorldWind.NewWidgets.FormWidget(“Time Control”);

m_window.Name = “Time Control”;

m_window.ClientSize = new System.Drawing.Size(300, 183);

// Bug in FormWidget required anchor to be set before Location and parent widget

m_window.Anchor = WorldWind.NewWidgets.WidgetEnums.AnchorStyles.Left | WorldWind.NewWidgets.WidgetEnums.AnchorStyles.Bottom;

m_window.ParentWidget = DrawArgs.NewRootWidget;

m_window.Location = new System.Drawing.Point(0, DrawArgs.NewRootWidget.ClientSize.Height - 183);

m_window.Text = “Double Click to Re-Open”;

m_window.BorderEnabled = false;

m_window.AutoHideHeader = true;

m_window.BackgroundColor = System.Drawing.Color.FromArgb(0, 0, 0, 0);

m_window.HeaderEnabled = true;

m_window.Visible = false;

time = new WorldWind.NewWidgets.PictureBox();

time.Name = “Time”;

time.ImageUri = basePath + “\\Data\\Icons\\Time\\time off.png”;

time.ClientLocation = new System.Drawing.Point(12, 59);

time.ClientSize = new System.Drawing.Size(42, 42);

time.Visible = true;

time.ParentWidget = m_window;

time.OnMouseEnterEvent += new EventHandler(time_OnMouseEnterEvent);

time.OnMouseLeaveEvent += new EventHandler(time_OnMouseLeaveEvent);

time.OnMouseUpEvent += new MouseEventHandler(time_OnMouseUpEvent);

time.CountHeight = false;

time.CountWidth = true;

m_window.ChildWidgets.Add(time);

play = new WorldWind.NewWidgets.PictureBox();

play.Name = “Play”;

if (TimeKeeper.Enabled)

{

play.ImageUri = basePath + “\\Data\\Icons\\Time\\play on.png”;

}

else

{

play.ImageUri = basePath + “\\Data\\Icons\\Time\\play off.png”;

}

play.ClientLocation = new System.Drawing.Point(50, 1);

play.ClientSize = new System.Drawing.Size(82, 82);

play.Visible = true;

play.ParentWidget = m_window;

play.OnMouseEnterEvent += new EventHandler(play_OnMouseEnterEvent);

play.OnMouseLeaveEvent += new EventHandler(play_OnMouseLeaveEvent);

play.OnMouseUpEvent += new System.Windows.Forms.MouseEventHandler(play_OnMouseUpEvent);

play.CountHeight = true;

play.CountWidth = true;

m_window.ChildWidgets.Add(play);

close = new WorldWind.NewWidgets.PictureBox();

close.Name = “Close”;

close.ImageUri = basePath + “\\Data\\Icons\\Time\\close off.png”;

close.ClientLocation = new System.Drawing.Point(29, 3);

close.ClientSize = new System.Drawing.Size(22, 22);

close.Visible = true;

close.ParentWidget = m_window;

close.OnMouseEnterEvent += new EventHandler(close_OnMouseEnterEvent);

close.OnMouseLeaveEvent += new EventHandler(close_OnMouseLeaveEvent);

close.OnMouseUpEvent += new MouseEventHandler(close_OnMouseUpEvent);

close.CountHeight = false;

close.CountWidth = false;

m_window.ChildWidgets.Add(close);

rewind = new WorldWind.NewWidgets.PictureBox();

rewind.Name = “Rewind”;

rewind.ImageUri = basePath + “\\Data\\Icons\\Time\\repeat off.png”;

rewind.ClientLocation = new System.Drawing.Point(16, 26);

rewind.ClientSize = new System.Drawing.Size(32, 32);

rewind.Visible = true;

rewind.ParentWidget = m_window;

rewind.OnMouseEnterEvent += new EventHandler(rewind_OnMouseEnterEvent);

rewind.OnMouseLeaveEvent += new EventHandler(rewind_OnMouseLeaveEvent);

rewind.OnMouseUpEvent += new MouseEventHandler(rewind_OnMouseUpEvent);

rewind.CountHeight = false;

rewind.CountWidth = false;

m_window.ChildWidgets.Add(rewind);

pause = new WorldWind.NewWidgets.PictureBox();

pause.Name = “Pause”;

if (TimeKeeper.Enabled)

{

pause.ImageUri = basePath + “\\Data\\Icons\\Time\\pause off.png”;

}

else

{

pause.ImageUri = basePath + “\\Data\\Icons\\Time\\pause on.png”;

}

pause.ClientLocation = new System.Drawing.Point(35, 88);

pause.ClientSize = new System.Drawing.Size(64, 64);

pause.Visible = true;

pause.ParentWidget = m_window;

pause.OnMouseEnterEvent += new EventHandler(pause_OnMouseEnterEvent);

pause.OnMouseLeaveEvent += new EventHandler(pause_OnMouseLeaveEvent);

pause.OnMouseUpEvent += new System.Windows.Forms.MouseEventHandler(pause_OnMouseUpEvent);

pause.CountHeight = true;

pause.CountWidth = false;

m_window.ChildWidgets.Add(pause);

slow = new WorldWind.NewWidgets.PictureBox();

slow.Name = “Slow”;

slow.ImageUri = basePath + “\\Data\\Icons\\Time\\slow off.png”;

slow.ClientLocation = new System.Drawing.Point(97, 88);

slow.ClientSize = new System.Drawing.Size(64, 64);

slow.Visible = true;

slow.ParentWidget = m_window;

slow.OnMouseEnterEvent += new EventHandler(slow_OnMouseEnterEvent);

slow.OnMouseLeaveEvent += new EventHandler(slow_OnMouseLeaveEvent);

slow.OnMouseUpEvent += new System.Windows.Forms.MouseEventHandler(slow_OnMouseUpEvent);

slow.CountHeight = false;

slow.CountWidth = false;

m_window.ChildWidgets.Add(slow);

fast = new WorldWind.NewWidgets.PictureBox();

fast.Name = “Fast”;

fast.ImageUri = basePath + “\\Data\\Icons\\Time\\fast off.png”;

fast.ClientLocation = new System.Drawing.Point(158, 88);

fast.ClientSize = new System.Drawing.Size(64, 64);

fast.Visible = true;

fast.ParentWidget = m_window;

fast.OnMouseEnterEvent += new EventHandler(fast_OnMouseEnterEvent);

fast.OnMouseLeaveEvent += new EventHandler(fast_OnMouseLeaveEvent);

fast.OnMouseUpEvent += new System.Windows.Forms.MouseEventHandler(fast_OnMouseUpEvent);

fast.CountHeight = false;

fast.CountWidth = false;

m_window.ChildWidgets.Add(fast);

timeLabel = new WorldWind.NewWidgets.TextLabel();

timeLabel.Name = “Current Time”;

timeLabel.ClientLocation = new System.Drawing.Point(134, 65);

timeLabel.ClientSize = new System.Drawing.Size(140, 60);

timeLabel.Visible = true;

timeLabel.ParentWidget = m_window;

timeLabel.Text = GetCurrentTimeString();

TimeKeeper.Elapsed += new System.Timers.ElapsedEventHandler(TimeKeeper_Elapsed);

timeLabel.CountHeight = false;

timeLabel.CountWidth = true;

timeLabel.WordBreak = true;

m_window.ChildWidgets.Add(timeLabel);

DrawArgs.NewRootWidget.ChildWidgets.Add(m_window);

m_toolbarItem = new WorldWind.NewWidgets.WidgetMenuButton(

“Time Controller”,

basePath + “\\Data\\Icons\\Time\\time off.png”,

m_window);

//向MenuBar中添加菜单按钮

ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_toolbarItem);

}

catch (Exception ex)

{

Log.Write(ex);

}

base.Load();

}

其他插件的重载后的Load()方法也是类似的,不再赘述,

希望能帮研究WW的朋友理清插件加载过程的思路,少走弯路。

篇2:WorldWind系列六:渲染过程解析篇

今天主要是分析学习了Render问题,搞明白了WorldWind中整个Render绘制处理过程,其中关键类是:RenderableObject.cs ,RenderobjectList.cs.

WW中所有需要绘制的对象都RenderableObject,WW的各功能的执行显示都是不断地调用相应的Render方法。

1.RenderableObject整个绘制对象继承图

WW绘制都是通过RenderableObject类,将所有的要绘制对象都看做是RenderableObject,从而统一了整个系统WW的绘制对象的绘制过程。

2.RenderableObjectList也继承自RenderableObject,先看看它的继承图

摘录内容:

“实际的点线,平面纹理等渲染对象都是从RenderableObject继承,最终的渲染实现也是在从它继续下来的类中,RenderableObjectList的成员m_children(protected ArrayList m_children = new ArrayList();)包含WW中所有的渲染对象,绘制过程中按如下的优先级进行:

public enum RenderPriority

{

SurfaceImages = 0,

TerrainMappedImages = 100,

AtmosphericImages = 200,

LinePaths = 300,

Icons = 400,

Placenames = 500,

Custom = 600

}

这里对WW调试过程中的m_children的成员做个截图,需要注意的是m_children的成员大部分还是 RenderableObjectList对象,向下包含的层次很多,但只有最底层的从RenderableObject继续的对象才是渲染的最终实现。”摘自:

blog.sina.com.cn/s/blog_467b6cd601008mmd.html~type=v5_one&label=rela_nextarticle

RenderableObjectList可以简单看作RenderableObject对象的集合,但实质上存储RenderableObject对象集合的仅仅是其中的属性m_children,它有很多特有的针对m_children管理的方法,如:Add(RenderableObject ro)、Remove(RenderableObject layer)。RenderableObjectList里通过该Timer.Elapsed 事件实现了自动刷新渲染的功能。这里还有个知识点,我们可以学习一下,就是Timer.Elapsed 事件使用,请参考MS的msdn.microsoft.com/zh-cn/library/system.timers.timer.elapsed(VS.80).aspx。

3.下面让我们一起看看WW实现渲染绘制的整个代码调用流程,主要分为两部分:一、获取到所有的要绘制对象集合,二、绘制所有要绘制的对象。分析入口还是从WorldWind.cs的MainAppliaction()方法开始的。

3.1获取到所有的要绘制对象集合,存放到World.cs中的 RenderableObjects属性里

MainAppliaction()中调用OpenStartupWorld()

——》2974行OpenWorld( curWorldFile );调用了private void OpenWorld(string worldXmlFile)方法

——》 3049行 worldWindow.CurrentWorld = WorldWind.ConfigurationLoader.Load(worldXmlFile, worldWindow.Cache);调用了CongfigurationLoader.cs的public static World Load(string filename, Cache cache)方法

——》CongfigurationLoader.cs 的110行 newWorld.RenderableObjects = getRenderablesFromLayerDirectory(layerDirectory, newWorld, cache); 看代码

加载渲染对象代码

public static World Load(string filename, Cache cache)

{

Log.Write(Log.Levels.Debug, “CONF”, “Loading ” + filename);

// get the World Wind Settings through reflection to avoid changing the signature of Load().

Assembly a = Assembly.GetEntryAssembly();

Type appType = a.GetType(“WorldWind.MainApplication”);

System.Reflection.FieldInfo finfo = appType.GetField(“Settings”, BindingFlags.Static | BindingFlags.Public | BindingFlags.GetField);

WorldWindSettings settings = finfo.GetValue(null) as WorldWindSettings;

XmlReaderSettings readerSettings = new XmlReaderSettings();

if (settings.ValidateXML)

{

Log.Write(Log.Levels.Debug, “CONF”, “validating ” + filename + “ against WorldXmlDescriptor.xsd and LayerSet.xsd”);

readerSettings.ValidationType = ValidationType.Schema;

/* load the schema to validate against instead of hoping for an inline schema reference */

XmlSchemaSet schemas = new XmlSchemaSet();

schemas.Add(null, settings.ConfigPath + “/WorldXmlDescriptor.xsd”);

schemas.Add(null, settings.ConfigPath + “/Earth/LayerSet.xsd”);

readerSettings.Schemas = schemas;

readerSettings.ValidationEventHandler += new ValidationEventHandler(XMLValidationCallback);

readerSettings.ValidationFlags |= System.Xml.Schema.XmlSchemaValidationFlags.ReportValidationWarnings;

}

else

{

Log.Write(Log.Levels.Debug, “CONF”, “loading ” + filename + “ without validation”);

readerSettings.ValidationType = ValidationType.None;

}

try

{

XmlReader docReader = XmlReader.Create(filename, readerSettings);

XPathDocument docNav = new XPathDocument(docReader);

XPathNavigator nav = docNav.CreateNavigator();

XPathNodeIterator worldIter = nav.Select(“/World[@Name]”);

if (worldIter.Count >0)

{

worldIter.MoveNext();

string worldName = worldIter.Current.GetAttribute(“Name”, “”);

double equatorialRadius = ParseDouble(worldIter.Current.GetAttribute(“EquatorialRadius”, “”));

string layerDirectory = worldIter.Current.GetAttribute(“LayerDirectory”, “”);

if (layerDirectory.IndexOf(“:”) < 0)

{

layerDirectory = Path.Combine(Path.GetDirectoryName(filename), layerDirectory);

}

TerrainAccessor[] terrainAccessor = getTerrainAccessorsFromXPathNodeIterator(worldIter.Current.Select(“TerrainAccessor”),

System.IO.Path.Combine(cache.CacheDirectory, worldName));

World newWorld = new World(

worldName,

new Microsoft.DirectX.Vector3(0, 0, 0),

new Microsoft.DirectX.Quaternion(0, 0, 0, 0),

equatorialRadius,

cache.CacheDirectory,

(terrainAccessor != null ? terrainAccessor[0] : null)//TODO: Oops, World should be able to handle an array of terrainAccessors

);

//加载所有要渲染绘制的对象

newWorld.RenderableObjects = getRenderablesFromLayerDirectory(layerDirectory, newWorld, cache);

return newWorld;

}

}

catch (XmlSchemaException ex)

{

Log.Write(Log.Levels.Error, “CONF”, “Exception caught during XML parsing: ” + ex.Message);

Log.Write(Log.Levels.Error, “CONF”, “File ” + filename + “ was not read successfully.”);

// TODO: should pop up a message box or something.

return null;

}

return null;

}

——》 170 public static RenderableObjectList getRenderableFromLayerFile(string layerFile, World parentWorld, Cache cache, bool enableRefresh)方法,真正加载绘制对象集合的函数。

3.2绘制所有要绘制的对象

WorldWind.cs中MainAppliaction()中

——》675worldWindow.Render();调用了WorldWindow.cs的Render()方法

——》785 m_World.Render(this.drawArgs);调用World.cs的public override void Render(DrawArgs drawArgs)方法

分类分层次地调用渲染代码

public override void Render(DrawArgs drawArgs)

{

try

{

if (m_WorldSurfaceRenderer != null && World.Settings.UseWorldSurfaceRenderer)

{

m_WorldSurfaceRenderer.RenderSurfaceImages(drawArgs);

}

// Old method -- problems with RenderPriority sorting

// RenderableObjects.Render(drawArgs);

RenderStars(drawArgs, RenderableObjects);

if (drawArgs.CurrentWorld.IsEarth && World.Settings.EnableAtmosphericScattering)

{

float aspectRatio = (float)drawArgs.WorldCamera.Viewport.Width / drawArgs.WorldCamera.Viewport.Height;

float zNear = (float)drawArgs.WorldCamera.Altitude * 0.1f;

double distToCenterOfPlanet = (drawArgs.WorldCamera.Altitude + equatorialRadius);

double tangentalDistance = Math.Sqrt(distToCenterOfPlanet * distToCenterOfPlanet - equatorialRadius * equatorialRadius);

double amosphereThickness = Math.Sqrt(m_outerSphere.m_radius * m_outerSphere.m_radius + equatorialRadius * equatorialRadius);

Matrix proj = drawArgs.device.Transform.Projection;

drawArgs.device.Transform.Projection = Matrix.PerspectiveFovRH((float)drawArgs.WorldCamera.Fov.Radians, aspectRatio, zNear, (float)(tangentalDistance + amosphereThickness));

drawArgs.device.RenderState.ZBufferEnable = false;

drawArgs.device.RenderState.CullMode = Cull.CounterClockwise;

m_outerSphere.Render(drawArgs);

drawArgs.device.RenderState.CullMode = Cull.Clockwise;

drawArgs.device.RenderState.ZBufferEnable = true;

drawArgs.device.Transform.Projection = proj;

}

if (World.Settings.EnableSunShading)

RenderSun(drawArgs);

//分类、分层次地调用渲染方法

//render SurfaceImages

Render(RenderableObjects, WorldWind.Renderable.RenderPriority.TerrainMappedImages, drawArgs);

if (m_projectedVectorRenderer != null)

m_projectedVectorRenderer.Render(drawArgs);

//render AtmosphericImages

Render(RenderableObjects, WorldWind.Renderable.RenderPriority.AtmosphericImages, drawArgs);

//render LinePaths

Render(RenderableObjects, WorldWind.Renderable.RenderPriority.LinePaths, drawArgs);

//render Placenames

Render(RenderableObjects, WorldWind.Renderable.RenderPriority.Placenames, drawArgs);

//render Icons

Render(RenderableObjects, WorldWind.Renderable.RenderPriority.Icons, drawArgs);

//render Custom

Render(RenderableObjects, WorldWind.Renderable.RenderPriority.Custom, drawArgs);

if (Settings.showPlanetAxis)

this.DrawAxis(drawArgs);

}

catch (Exception ex)

{

Log.Write(ex);

}

}

——》分类绘制过程中是调用 485行的private void Render(WorldWind.Renderable.RenderableObject renderable, WorldWind.Renderable.RenderPriority priority, DrawArgs drawArgs)方法,

被各类对象调用的渲染方法

private void Render(WorldWind.Renderable.RenderableObject renderable, WorldWind.Renderable.RenderPriority priority, DrawArgs drawArgs)

{

if (!renderable.IsOn || (renderable.Name != null && renderable.Name.Equals(“Starfield”)))

return;

try

{

if (priority == WorldWind.Renderable.RenderPriority.Icons && renderable is Icons)

{

//关键代码,真正调用DirectX实施渲染绘制的,Render()方法被RenderObject类的子类渲染对象重载,实际上调用的是子类的Render()方法。

renderable.Render(drawArgs);

}

else if (renderable is WorldWind.Renderable.RenderableObjectList)

{

WorldWind.Renderable.RenderableObjectList rol = (WorldWind.Renderable.RenderableObjectList)renderable;

for (int i = 0; i < rol.ChildObjects.Count; i++)

{

Render((WorldWind.Renderable.RenderableObject)rol.ChildObjects[i], priority, drawArgs);

}

}

// hack at the moment

else if (priority == WorldWind.Renderable.RenderPriority.TerrainMappedImages)

{

if (renderable.RenderPriority == WorldWind.Renderable.RenderPriority.SurfaceImages || renderable.RenderPriority == WorldWind.Renderable.RenderPriority.TerrainMappedImages)

{

renderable.Render(drawArgs);

}

}

else if (renderable.RenderPriority == priority)

{

renderable.Render(drawArgs);

}

}

catch (Exception ex)

{

Log.Write(ex);

}

}

说明:该方法中596行 renderable.Render(drawArgs);实质上是调用各个RenderableObject具体的子类重写的Render()方法,实现绘制的。

4.以WavingFlagLayer.cs类重写的588行Render()方法为例,看看是如何完成绘制的。

WavingFlagLayer类渲染代码

public override void Render(DrawArgs drawArgs)

{

if (!isInitialized)

return;

if (m_polygonFeature == null || !drawArgs.WorldCamera.ViewFrustum.Intersects(m_polygonFeature.BoundingBox))

return;

try

{

double ffset = 0;

if (Bar3D != null && Bar3D.IsOn)

{

Bar3D.Render(drawArgs);

ffset = Bar3D.RenderedHeight;

}

Cull cull = drawArgs.device.RenderState.CullMode;

drawArgs.device.RenderState.CullMode = Cull.None;

drawArgs.device.RenderState.ZBufferEnable = true;

drawArgs.device.TextureState[0].ColorOperation = TextureOperation.SelectArg1;

drawArgs.device.TextureState[0].ColorArgument1 = TextureArgument.TextureColor;

Vector3 surfacePos = MathEngine.SphericalToCartesian(m_latitude, m_longitude, World.EquatorialRadius);

Vector3 rc = new Vector3(

(float)drawArgs.WorldCamera.ReferenceCenter.X,

(float)drawArgs.WorldCamera.ReferenceCenter.Y,

(float)drawArgs.WorldCamera.ReferenceCenter.Z

);

Vector3 projectedPoint = drawArgs.WorldCamera.Project(surfacePos - rc);

int mouseBuffer = 15;

if (projectedPoint.X >DrawArgs.LastMousePosition.X - mouseBuffer &&

projectedPoint.X < DrawArgs.LastMousePosition.X + mouseBuffer &&

projectedPoint.Y >DrawArgs.LastMousePosition.Y - mouseBuffer &&

projectedPoint.Y < DrawArgs.LastMousePosition.Y + mouseBuffer)

{

if (!m_isMouseInside)

{

m_isMouseInside = true;

if (OnMouseEnterEvent != null)

{

OnMouseEnterEvent(this, null);

}

}

}

else

{

if (m_isMouseInside)

{

m_isMouseInside = false;

if (OnMouseLeaveEvent != null)

{

OnMouseLeaveEvent(this, null);

}

}

}

drawArgs.device.RenderState.CullMode = Cull.None;

if (ShowHighlight)

renderHighlight(drawArgs);

RenderFlag(drawArgs, offset);

drawArgs.device.RenderState.CullMode = cull;

}

catch (Exception ex)

{

Log.Write(ex);

}

}

WorldWind系列十四:DEM数据加载和应用――以SRTM为例(下)

心理学考研之“语言”全解析

小升初修改病句全解(五)

华东五市全陪导游词

《大道之行也》中考试题全解析

关于商务英语写作的过程与基本要求解析

饮酒其五的全诗鉴赏

浮天水送无穷树全诗解析

历年高考语文成语题(五)含解析

古诗词答题模式解析——一词领全诗型

《WorldWind系列五:插件加载过程全解析(精选2篇).doc》
将本文的Word文档下载到电脑,方便收藏和打印
推荐度:
点击下载文档

文档为doc格式

最新推荐
猜你喜欢
点击下载本文文档