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


    之前的一篇博客是关于加载粗三维模型的,见http://blog.csdn.net/giser_whu/article/details/43452703,这个地方还存在着不能加载纹理的问题,一直没呢解决。那么WW如何加载常用的三维模型格式(3ds、obj、skp)呢,通过一番搜索,了解到WW可以加载collada的dae格式的三维模型,并且还可以加载kmlkmz文件,那么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. }  
  • 相关阅读:
    MyBatis mapper.xml中SQL处理小于号与大于号 和小于等于号
    iOS打包时Export的四个选择是什么意思?
    Xcode中New Build System和 Legacy build system的区别
    Xcode中Debug、Profile、Release的区别
    versionCode和versionName区别
    Android Studio 3.5 plugin中找不到Flutter插件
    Javascript 面向对象编程(一):封装
    Flutter-常用第三方库
    iOS info.plist 中的隐私权限
    Flutter打包ios应用流程详解
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6774792.html
Copyright © 2020-2023  润新知