今天主要是分析学习了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继续的对象才是渲染的最终实现。”摘自:

http://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的http://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 offset = 0;

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

Bar3D.Render(drawArgs);
                    offset = 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学习系列五:插件加载过程全解析

WorldWind学习系列四:功能分析——Show Planet Axis、Show Position 、Show Cross Hairs功能

WorldWind学习系列三:简单功能分析——主窗体的键盘监听处理及拷贝和粘贴位置坐标功能

WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析

WorldWind学习系列二:擒贼先擒王篇2

WorldWind学习系列二:擒贼先擒王篇1

WorldWind学习系列一:顺利起航篇

转载于:https://www.cnblogs.com/wuhenke/archive/2009/12/14/1624122.html

WorldWind学习系列六:渲染过程解析篇相关推荐

  1. WorldWind学习系列一:顺利起航篇

    今天从官方下载WorldWind 1.4版的源代码开始研究,可是运行时,发现有很多问题.下面是我的解决对策,帮助遇到相同问题的网友顺利起航! 错误1:      原因:无法找到引用的DLL文件 解决方 ...

  2. Android音视频学习系列(六) — 掌握视频基础知识并使用OpenGL ES 2.0渲染YUV数据

    系列文章 Android音视频学习系列(一) - JNI从入门到精通 Android音视频学习系列(二) - 交叉编译动态库.静态库的入门 Android音视频学习系列(三) - Shell脚本入门 ...

  3. WorldWind学习系列十五:如何切割影像和DEM数据及其在WW中的应用配置

    原文转自:http://www.cnblogs.com/wuhenke/archive/2010/01/03/1638499.html WorldWind学习系列十四中我从代码上分析如何加载DEM数据 ...

  4. STM32-USB学习系列(六):USB-HID键盘的实现以及键盘报文描述符的简介

    目录 一.整体步骤 二.USB 鼠标HID更改成键盘HID步骤 1.使用STM32CubeMX生成鼠标HID模版,并且进行修改 2.修改HID的接口描述符与报文描述符 3.修改USBD_HID_Set ...

  5. Android-PickerView系列之源码解析篇(二)

    前言 WheelView想必大家或多或少都有一定了解, 它是一款3D滚轮控件,效果类似IOS 上面的UIpickerview .按照国际惯例,先放一张效果图: 以上是Android-PickerVie ...

  6. 渲染系列--图像渲染过程

    图像渲染过程 图像渲染大概经过了四个阶段,分别是应用处理阶段.几何处理阶段.光栅化阶段以及像素处理阶段,如下图所示,其中应用处理阶段CPU还在处理,CPU需要对图像进行操作和改变,将生成的图元信息交给 ...

  7. WorldWind学习系列七:Load/Unload Plugins——投石问路篇

    原文转自:http://www.cnblogs.com/wuhenke/archive/2009/12/15/1625102.html 今天原计划把Load/Unload Plugins完全弄明白,可 ...

  8. 浏览器解析jsx_preact 源码学习系列之一:JSX解析与DOM渲染

    前言 一直以来我都想研究 React 的源码,但总是看不懂.即便是去翻看最早的源码,代码量也有1万多行,研究起来难度太高了,这个问题困扰了我很久. 直到前两天我跟同事讨论起这个问题,忽然发现一个可行的 ...

  9. WorldWind学习系列十一:Virtual Earth插件学习

    学习WorldWind有很长时间了,理论学习算是基本完成了.我体会是WW的学习主要分为两大步:WW框架体系学习和WW插件学习.学习WW插件逐步深入后,必然要首先学习Direct3D编程,这也算是我的经 ...

  10. WorldWind学习系列:5、摄像机类

    摄像机将现实世界中的物体通过世界变换.相机变换.投影变换和视图变换投影到屏幕空间,世界变换决定物体在世界坐标系的位置.大小.朝向等,观察变换将物体变换到以相机为原点的坐标系统中,投影变换按近大远小的投 ...

最新文章

  1. liferay学习(源码调试问题)
  2. 工作302:scss目录编写
  3. 写日历的程序员,你必须弄懂的中国农历算法。
  4. 如何使用Postman和Newman在CI环境中自动化REST API端到端测试
  5. (23)css3文字阴影text-shadow
  6. Spring Boot实践
  7. vue 存储对象 不要监听_Vue源码解析----响应式原理
  8. Python和js之间的转换
  9. DB2 常用SQL语法
  10. qt中如何刷新一下屏幕_感情维护:如何在恋爱关系中分开一下,然后更坚强地回来...
  11. Thymeleaf 教程
  12. 跨越千年的RSA算法
  13. 百度搜索结果的URL参数 搜索历史记录(rsv_sug)
  14. 支持安卓与iphone13和安卓手机的5W无线充电芯片IC
  15. Spring Boot 框架学习笔记(五)( SpringSecurity安全框架 )
  16. python3版本升级和系统更新_如何更新mac系统自带的python版本到最新3.3
  17. qt 频谱 音乐播放器
  18. 博弈论 —— 海盗分金
  19. Scaled-YOLOv4: Scaling Cross Stage Partial Network 论文翻译
  20. 51nod 1326 遥远的旅途

热门文章

  1. Hadoop数据分析实例:P2P借款人信用风险实时监控模型设计
  2. 一个博友的SQL问题解决过程
  3. Unity调用Android类方法
  4. linux入门基础命令详解
  5. Linq 支持动态字查询集合, 也就是说根据传入的值进行查询。
  6. 2005年7月19日
  7. CenterNet :Objects as Points/CenterTrack:Tracking Objects as Points
  8. mapreduce数据压缩
  9. CSS小技巧--文字对齐
  10. Aspose.Excel模板输出中名称管理器的使用