World Wind Java开发之十五——加载三维模型(转)

之前的一篇博客是关于加载粗三维模型的,见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.源代码

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