之前的一篇博客是关于加载粗三维模型的,见http://blog.csdn.net/giser_whu/article/details/43452703,这个地方还存在着不能加载纹理的问题,一直没呢解决。那么WW如何加载常用的三维模型格式(3ds、obj、skp)呢,通过一番搜索,了解到WW可以加载collada的dae格式的三维模型,并且还可以加载kml\kmz文件,那么WW加载三维模型的方法就出来了:首先将其他格式三维模型转换为kmz或kml文件,再加载。这里我是从su的三维模型库中下载的skp文件,在su中可以直接转换为kmz文件,通过测试,这个方法是可行的。先来看下效果图:

1.效果图

第一幅是德国标志性建筑——柏林奥林匹克体育场,可以看到效果还是可以的,不过没有使用lod技术,一旦模型数量增多,会卡顿。
 
第二幅是也是德国地标性建筑——柏林电视塔。
 
第三幅是3D City DB上的德国柏林一些collada三维模型,需要的可以去下载做下测试

2.实现方法

开头已经明确了WW加载三维模型的路线,WW又提供了加载kml/kmz文件的demo(KMLViewer),所以要实现这个是很简单的了,只需根据自己的需要改动原demo,整合到自己的工程下即可,这里我改动原demo,编写了SmartScopeKMLViewer,方法参见之前的博客。所用到的数据,整理完上传到CSDN资源,需要的可以去下载。下载地址:http://download.csdn.net/detail/liushuo_whu/8512739

3.源代码

  1. /*
  2. Copyright (C) 2001, 2010 United States Government
  3. as represented by the Administrator of the
  4. National Aeronautics and Space Administration.
  5. All Rights Reserved.
  6. */
  7. package gov.nasa.worldwindx.examples.kml;
  8. import gov.nasa.worldwind.WorldWind;
  9. import gov.nasa.worldwind.avlist.AVKey;
  10. import gov.nasa.worldwind.awt.WorldWindowGLCanvas;
  11. import gov.nasa.worldwind.layers.RenderableLayer;
  12. import gov.nasa.worldwind.ogc.kml.KMLAbstractFeature;
  13. import gov.nasa.worldwind.ogc.kml.KMLRoot;
  14. import gov.nasa.worldwind.ogc.kml.impl.KMLController;
  15. import gov.nasa.worldwind.render.Offset;
  16. import gov.nasa.worldwind.retrieve.RetrievalService;
  17. import gov.nasa.worldwind.util.WWIO;
  18. import gov.nasa.worldwind.util.WWUtil;
  19. import gov.nasa.worldwind.util.layertree.KMLLayerTreeNode;
  20. import gov.nasa.worldwind.util.layertree.KMLNetworkLinkTreeNode;
  21. import gov.nasa.worldwind.util.layertree.LayerTree;
  22. import gov.nasa.worldwindx.examples.util.BalloonController;
  23. import gov.nasa.worldwindx.examples.util.HotSpotController;
  24. import java.beans.PropertyChangeEvent;
  25. import java.beans.PropertyChangeListener;
  26. import java.io.File;
  27. import java.io.IOException;
  28. import java.net.URL;
  29. import javax.swing.SwingUtilities;
  30. import javax.xml.stream.XMLStreamException;
  31. /**
  32. * 导入KML或KMZ文件,以图层形式查看,KML或KMZ文件的内容显示为一个要素树。在要素树上点击KML要素可以查看该要素
  33. * ,在球上点击要素可以弹出要素的描述信息框
  34. */
  35. public class SmartScopeKMLViewer
  36. {
  37. public static class KMLUtil
  38. {
  39. protected LayerTree layerTree; // 图层树
  40. protected RenderableLayer hiddenLayer; // 渲染图层(图层树)
  41. protected HotSpotController hotSpotController; // 热点controller
  42. protected KMLApplicationController kmlAppController; // KMLcontroller
  43. protected BalloonController balloonController; // BalloonController
  44. protected WorldWindowGLCanvas wwd; // ww
  45. public KMLUtil(WorldWindowGLCanvas worldWindowGLCanvas)
  46. {
  47. this.wwd = worldWindowGLCanvas;
  48. // 初始化图层树
  49. this.layerTree = new LayerTree(new Offset(20d, 160d, AVKey.PIXELS,
  50. AVKey.INSET_PIXELS));
  51. // this.layerTree.getModel().refresh(this.wwd.getModel().getLayers());
  52. // 图层树渲染图层
  53. this.hiddenLayer = new RenderableLayer();
  54. this.hiddenLayer.addRenderable(this.layerTree);
  55. this.wwd.getModel().getLayers().add(this.hiddenLayer);
  56. // 注册图层选择和气球热点选择事件监听
  57. this.hotSpotController = new HotSpotController(this.wwd);
  58. // 注册kml事件监听
  59. this.kmlAppController = new KMLApplicationController(this.wwd);
  60. this.balloonController = new BalloonController(this.wwd)
  61. {
  62. @Override
  63. protected void addDocumentLayer(KMLRoot document)
  64. {
  65. addKMLLayer(document);
  66. }
  67. };
  68. // 关联kml管理器和balloon管理器
  69. this.kmlAppController.setBalloonController(balloonController);
  70. // Set up to receive SSLHandshakeExceptions that occur during
  71. // resource retrieval.
  72. WorldWind.getRetrievalService().setSSLExceptionListener(
  73. new RetrievalService.SSLExceptionListener()
  74. {
  75. public void onException(Throwable e, String path)
  76. {
  77. System.out.println(path);
  78. System.out.println(e);
  79. }
  80. });
  81. }
  82. /**
  83. *
  84. * @方法名称: addKMLLayer ;
  85. * @方法描述: 添加KML图层: ;
  86. * @参数 :@param kmlRoot
  87. * @返回类型: void ;
  88. * @创建人:bluce ;
  89. * @创建时间:2015年3月17日 下午7:54:40;
  90. * @throws
  91. */
  92. protected void addKMLLayer(KMLRoot kmlRoot)
  93. {
  94. // Create a KMLController to adapt the KMLRoot to the World Wind
  95. KMLController kmlController = new KMLController(kmlRoot);
  96. // 添加kml图层
  97. RenderableLayer layer = new RenderableLayer();
  98. layer.setName((String) kmlRoot.getField(AVKey.DISPLAY_NAME));
  99. layer.addRenderable(kmlController);
  100. this.wwd.getModel().getLayers().add(layer);
  101. // 添加kml图层树节点
  102. KMLLayerTreeNode layerNode = new KMLLayerTreeNode(layer, kmlRoot);
  103. this.layerTree.getModel().addLayer(layerNode);
  104. this.layerTree.makeVisible(layerNode.getPath());
  105. layerNode.expandOpenContainers(this.layerTree);
  106. // Listens to refresh property change events from KML network link
  107. // nodes. Upon receiving such an event this
  108. // expands any tree paths that represent open KML containers. When a
  109. // KML network link refreshes, its tree
  110. // node replaces its children with new nodes created from the
  111. // refreshed content, then sends a refresh
  112. // property change event through the layer tree. By expanding open
  113. // containers after a network link refresh,
  114. // we ensure that the network link tree view appearance is
  115. // consistent with the KML specification.
  116. layerNode.addPropertyChangeListener(
  117. AVKey.RETRIEVAL_STATE_SUCCESSFUL,
  118. new PropertyChangeListener()
  119. {
  120. public void propertyChange(
  121. final PropertyChangeEvent event)
  122. {
  123. if (event.getSource() instanceof KMLNetworkLinkTreeNode)
  124. {
  125. // Manipulate the tree on the EDT.
  126. SwingUtilities.invokeLater(new Runnable()
  127. {
  128. public void run()
  129. {
  130. ((KMLNetworkLinkTreeNode) event
  131. .getSource())
  132. .expandOpenContainers(layerTree);
  133. wwd.redraw();
  134. }
  135. });
  136. }
  137. }
  138. });
  139. }
  140. }
  141. /**
  142. *
  143. * @项目名称:worldwind-1.5.0
  144. * @类名称:WorkerThread
  145. * @类描述:加载KML文件线程类
  146. * @创建人:bluce
  147. * @创建时间:2015年3月17日 下午7:58:38
  148. * @修改备注:
  149. * @版本:
  150. */
  151. public static class WorkerThread extends Thread
  152. {
  153. /**
  154. * 待加载kml文件,在构造函数中初始化
  155. */
  156. protected Object kmlSource;
  157. /**
  158. * kmlapp
  159. */
  160. protected KMLUtil KMLUtil;
  161. public WorkerThread(Object kmlSource, KMLUtil KMLUtil)
  162. {
  163. this.kmlSource = kmlSource;
  164. this.KMLUtil = KMLUtil;
  165. }
  166. /**
  167. * Loads this worker thread's KML source into a new
  168. * <code>{@link gov.nasa.worldwind.ogc.kml.KMLRoot}</code>, then adds
  169. * the new <code>KMLRoot</code> to this worker thread's
  170. * <code>AppFrame</code>. The <code>KMLRoot</code>'s
  171. * <code>AVKey.DISPLAY_NAME</code> field contains a display name created
  172. * from either the KML source or the KML root feature name.
  173. * <p/>
  174. * If loading the KML source fails, this prints the exception and its
  175. * stack trace to the standard error stream, but otherwise does nothing.
  176. */
  177. public void run()
  178. {
  179. try
  180. {
  181. KMLRoot kmlRoot = this.parse();
  182. // 设置文档的显示名称
  183. kmlRoot.setField(AVKey.DISPLAY_NAME,
  184. formName(this.kmlSource, kmlRoot));
  185. // 启动一个任务进程加载解析的kml文件
  186. final KMLRoot finalKMLRoot = kmlRoot;
  187. SwingUtilities.invokeLater(new Runnable()
  188. {
  189. public void run()
  190. {
  191. KMLUtil.addKMLLayer(finalKMLRoot);
  192. }
  193. });
  194. }
  195. catch (Exception e)
  196. {
  197. e.printStackTrace();
  198. }
  199. }
  200. /**
  201. *
  202. * @方法名称: parse ;
  203. * @方法描述: 解析KML文档 ;
  204. * @参数 :@return 返回KMLRoot
  205. * @参数 :@throws IOException:文档不可读
  206. * @参数 :@throws XMLStreamException :文档解析出现错误
  207. * @返回类型: KMLRoot ;
  208. * @创建人:bluce  ;
  209. * @创建时间:2015年3月17日 下午8:02:59;
  210. * @throws
  211. */
  212. protected KMLRoot parse() throws IOException, XMLStreamException
  213. {
  214. // KMLRoot.createAndParse will attempt to parse the document using a
  215. // namespace aware parser, but if that
  216. // fails due to a parsing error it will try again using a namespace
  217. // unaware parser. Note that this second
  218. // step may require the document to be read from the network again
  219. // if the kmlSource is a stream.
  220. return KMLRoot.createAndParse(this.kmlSource);
  221. }
  222. }
  223. protected static String formName(Object kmlSource, KMLRoot kmlRoot)
  224. {
  225. KMLAbstractFeature rootFeature = kmlRoot.getFeature();
  226. if (rootFeature != null && !WWUtil.isEmpty(rootFeature.getName()))
  227. return rootFeature.getName();
  228. if (kmlSource instanceof File)
  229. return ((File) kmlSource).getName();
  230. if (kmlSource instanceof URL)
  231. return ((URL) kmlSource).getPath();
  232. if (kmlSource instanceof String
  233. && WWIO.makeURL((String) kmlSource) != null)
  234. return WWIO.makeURL((String) kmlSource).getPath();
  235. return "KML Layer";
  236. }
  237. }

World Wind Java开发之十五——加载三维模型(转)的更多相关文章

  1. World Wind Java开发之十二——加载粗制三维模型(ExtrudedPolygon)(转)

    ww可以根据DLG图批量生成假三维模型,这对于小区等特征相似的建筑物模型的构建是非常有用的.下面来看如何一步步实现假三维模型的加载: 1.Shp文件的制作 首先在arcmap下数字化几个建筑物,并新建 ...

  2. World Wind Java开发之十五——载入三维模型

    之前的一篇博客是关于载入粗三维模型的,见http://blog.csdn.net/giser_whu/article/details/43452703,这个地方还存在着不能载入纹理的问题,一直没呢解决 ...

  3. World Wind Java开发之十四——添加WMS地图服务资源(转)

    数据是GIS的核心,没有数据一切无从谈起,Internet上有很多在线WMS地图服务资源,我们可以好好利用这些数据资源,比如天地图.必应地图.NASA.OGC数据服务等等. 在我们国家常用的还是天地图 ...

  4. Java开发学习(十五)----AOP入门案例及其工作流程解析

    一.AOP简介 1.1 什么是AOP AOP(Aspect Oriented Programming)面向切面编程,一种编程范式,指导开发者如何组织程序结构. OOP(Object Oriented ...

  5. World Wind Java开发之十——AnalyticSurface栅格渲染(转)

    http://blog.csdn.net/giser_whu/article/details/43017881 1.AnalyticSurfaceDemo ArcGIS下对栅格的各种分级渲染效果是非常 ...

  6. Java进阶(二十五)Java连接mysql数据库(底层实现)

    Java进阶(二十五)Java连接mysql数据库(底层实现) 前言 很长时间没有系统的使用java做项目了.现在需要使用java完成一个实验,其中涉及到java连接数据库.让自己来写,记忆中已无从搜 ...

  7. 马凯军201771010116《面向对象与程序设计Java》第十五周学习知识总结

    实验十五  GUI编程练习与应用程序部署 一.知识学习部分 清单文件 每个JAR文件中包含一个用于描述归档特征的清单文件(manifest).清单文件被命名为MANIFEST.MF,它位于JAR文件的 ...

  8. “全栈2019”Java多线程第二十五章:生产者与消费者线程详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  9. “全栈2019”Java多线程第十五章:当后台线程遇到finally

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

随机推荐

  1. 三层登录——C#版

    前言 前期了解三层架构主要是由UI层.BLL层和DAL层三部分构成.看到大牛们都采用三层的思想实现了登录,本菜鸟暗暗地站在了他们的肩膀上. 自己理解 对于三层自己的理解是:就像我们对一个大型的公司去找 ...

  2. Eclipse项目中乱码问题的解决办法

    一.产生的原因: 1.Http协议进行通信的时候是基于请求和响应的,传输的内容我们称之为报文! 2.Http协议会按照一定的规则将报文编码,然后在读取的时候再使用响应的解码格式进行解码! 3.这个一定 ...

  3. 开发外包注意事项——iOS APP的开发

    1. APP外包的流程是怎样的? 一般外包的项目都需要经常这几个流程: 1)需求沟通:双方沟通项目的需求,对项目的可行性进行分析 2)工作量评估:在确认了项目的需求后,外包团队对项目的价钱和进度进行评 ...

  4. Java基础笔记(十三)——面向对象

    类和对象 类是具有相同属性和方法的一组对象的集合,好比一个虚拟的轮廓(抽象的概念),确定对象将会拥有的特征(属性)和行为(方法). 对象是类的实例表现,是一个具体的东西(一个看得到.摸得着的具体实体) ...

  5. [Leetcode]005. Longest Palindromic Substring

    public String longestPalindrome(String s) { int start = 0, end = 0; for (int i = 0; i < s.length( ...

  6. 基于Python Selenium Unittest PO设计模式详解

    本文章会讲述以下几个内容: 1.什么是PO设计模式(Page Object Model) 2.为什么要使用PO设计模式 3.使用PO设计模式要点 4.PO设计模式实例 1.什么是PO设计模式 (Pag ...

  7. 如何自动更新SVN项目

    在桌面新建“SVN Update.bat”文件,把下面的命令复制到该文件中,保存并退出,然后使用windows的“任务计划”功能,就可以实现定时自动更新SVN目录. 按此批处理文件的方法执行,一次可自 ...

  8. UVALive - 4223(hdu 2926)

    ---恢复内容开始--- 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2962 Trucking Time Limit: 20000/10000 MS ...

  9. 1160: sundari && Shortest path HDU - 4479

    http://gdutcode.sinaapp.com/problem.php?id=1160 http://acm.hdu.edu.cn/showproblem.php?pid=4479 35 51 ...

  10. Linux Shell中的反引号,单引号,双引号

    反引号位 (`) 位于键盘的Tab键的上方.1键的左方.注意与单引号(')位于Enter键的左方的区别. 在Linux中起着命令替换的作用.命令替换是指shell能够将一个命令的标准输出插在一个命令行 ...