查看: 2453|回复: 7

做一个类似谷歌地球的东西

[复制链接]

该用户从未签到

发表于 2010-8-10 14:38:58 | 显示全部楼层 |阅读模式
我现在有几个地区的清晰的卫星地图,想做成类似谷歌地球那样的软件。就是把这些卫星图按照经纬度贴在地球表面。我刚刚接触osg,有这么几个问题。(请大家指教一下,或者告诉我看哪些例子。osg里面的例子实在太多了,虽然很经典。)

1。怎么确定球体上的经纬度,这个经纬度和显示器坐标怎么对应。
2。osg可以在物体表面指定的区域内贴图吗?怎么把卫星图贴在指定的经纬度坐标范围内。
3。因为卫星图非常大,可能导致程序运行很慢。是不是需要使用mipmap?具体怎么操作或者需要学习哪些方面内容请大家给我说一下。


谢谢各位了、·~~~~

该用户从未签到

发表于 2010-8-11 08:45:53 | 显示全部楼层
您提到的这些问题,OSG完全可以实现~~~您的意图似乎是想底层架构一个球,所以,建议您WorldWind,,跟Google Earth差不多的东西,,基于D3D的,,开源的,有C#和Java版的~先明白球的具体实现原理,再用OSG实现的难度不大~~

该用户从未签到

 楼主| 发表于 2010-8-11 09:19:40 | 显示全部楼层
本帖最后由 TsChus 于 2010-8-11 11:37 编辑

2# FlySky

谢谢您的回答,另外一个问题。关于mipmap的。

我看了您在回答一个人的回帖中上传的自己写的mipmap的那个代码,我用32*32,16*16,8*8,4*4,2*2,1*1的几张图,从文件读入。已经可以了。


现在问题是,我每一级的图片都太大了,我看您说要分成小图片。我把每一级的图片都分成512*512了,于是每一级图片变成了很多张512*512的小图。但是,我不清楚接下来我怎么办??

期待您的回答!



我想用TextureRectangle,可是平面上没有贴图,而且会有warning,说没有提供有效的TextureRectangle。

该用户从未签到

 楼主| 发表于 2010-8-11 09:31:39 | 显示全部楼层
本帖最后由 TsChus 于 2010-8-11 11:38 编辑

2# FlySky

谢谢flysky这些天的回答,受益匪浅!!!

该用户从未签到

发表于 2010-8-11 11:45:09 | 显示全部楼层
不太明白您的实现,,给您一个mipmap的实例:



  1. /**********************************************************
  2. *Write by FlySky
  3. *zzuxp@163.com  http://ww.OsgChina.org   
  4. **********************************************************/

  5. #include <osgViewer/Viewer>

  6. #include <osg/Node>
  7. #include <osg/Geode>
  8. #include <osg/Group>
  9. #include <osg/Image>
  10. #include <osg/TexGen>
  11. #include <osg/Texture1D>
  12. #include <osg/TexEnv>
  13. #include <osg/StateSet>

  14. #include <osgDB/ReadFile>
  15. #include <osgDB/WriteFile>

  16. #include <osgUtil/Optimizer>


  17. //创建一个四边形
  18. osg::ref_ptr<osg::Geode> createQuad()
  19. {
  20.         osg::ref_ptr<osg::Geode> geode = new osg::Geode() ;

  21.         osg::ref_ptr<osg::Geometry> geom = new osg::Geometry() ;
  22.         geode->addDrawable(geom.get());

  23.         //设置顶点
  24.         osg::ref_ptr<osg::Vec3Array> vec = new osg::Vec3Array;
  25.         vec->push_back(osg::Vec3(-10.0f,0.0f,-10.0f));
  26.         vec->push_back(osg::Vec3(-10.0f,0.0f,10.0f));
  27.         vec->push_back(osg::Vec3(10.0f,0.0f,10.0f));
  28.         vec->push_back(osg::Vec3(10.0f,0.0f,-10.0f));

  29.         geom->setVertexArray(vec.get());

  30.         //设置法线
  31.         osg::ref_ptr<osg::Vec3Array> nor = new osg::Vec3Array;
  32.         nor->push_back( osg::Vec3f( 0.0f, -1.0f, 0.0f ) );

  33.         geom->setNormalArray(nor.get());       
  34.         geom->setNormalBinding(osg::Geometry::BIND_PER_PRIMITIVE_SET);


  35.         //设置纹理坐标
  36.         osg::ref_ptr<osg::Vec2Array> tex = new osg::Vec2Array;
  37.         tex->push_back( osg::Vec2f(0.0f, 0.0f) );
  38.         tex->push_back( osg::Vec2f(0.0f, 1.0f) );
  39.         tex->push_back( osg::Vec2f(1.0f, 1.0f) );
  40.         tex->push_back( osg::Vec2f(1.0f, 0.0f) );

  41.         geom->setTexCoordArray(0,tex.get());

  42.         geom->addPrimitiveSet( new osg::DrawArrays( osg::PrimitiveSet::QUADS, 0, 4 ) );

  43.         return geode.get();
  44. }

  45. static void fillImage(unsigned char* ptr, unsigned int size)
  46. {
  47.         //白色
  48.         if (size==1)
  49.         {
  50.                 float r = 0.5f;
  51.                 osg::Vec4 color(1.0f,1.0f,1.0f,1.0f);
  52.                 *ptr++ = (unsigned char)((color[0])*255.0f);
  53.                 *ptr++ = (unsigned char)((color[1])*255.0f);
  54.                 *ptr++ = (unsigned char)((color[2])*255.0f);
  55.                 *ptr++ = (unsigned char)((color[3])*255.0f);                       
  56.         }

  57.         //蓝色
  58.         if(size==2)
  59.         {
  60.                 osg::Vec4 color(0.0f,0.0f,1.0f,1.0f);
  61.                 for(unsigned int r=0;r<size;++r)
  62.                 {
  63.                         for(unsigned int c=0;c<size;++c)
  64.                         {
  65.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  66.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  67.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  68.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  69.                         }
  70.                 }
  71.         }

  72.         //黄色
  73.         if(size==4)
  74.         {
  75.                 osg::Vec4 color(0.0f,1.0f,0.0f,1.0f);
  76.                 for(unsigned int r=0;r<size;++r)
  77.                 {
  78.                         for(unsigned int c=0;c<size;++c)
  79.                         {
  80.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  81.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  82.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  83.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  84.                         }
  85.                 }
  86.         }

  87.         //红色
  88.         if(size==8)
  89.         {
  90.                 osg::Vec4 color(1.0f,0.0f,0.0f,1.0f);
  91.                 for(unsigned int r=0;r<size;++r)
  92.                 {
  93.                         for(unsigned int c=0;c<size;++c)
  94.                         {
  95.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  96.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  97.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  98.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  99.                         }
  100.                 }
  101.         }

  102.         //粉红色
  103.         if(size==16)
  104.         {
  105.                 osg::Vec4 color(1.0f,0.0f,1.0f,1.0f);
  106.                 for(unsigned int r=0;r<size;++r)
  107.                 {
  108.                         for(unsigned int c=0;c<size;++c)
  109.                         {
  110.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  111.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  112.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  113.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  114.                         }
  115.                 }
  116.         }

  117.         //黄色
  118.         if(size==32)
  119.         {
  120.                 osg::Vec4 color(1.0f,1.0f,0.0f,1.0f);
  121.                 for(unsigned int r=0;r<size;++r)
  122.                 {
  123.                         for(unsigned int c=0;c<size;++c)
  124.                         {
  125.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  126.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  127.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  128.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  129.                         }
  130.                 }
  131.         }

  132.         //蓝绿色
  133.         if(size==64)
  134.         {
  135.                 osg::Vec4 color(0.0f,1.0f,1.0f,1.0f);
  136.                 for(unsigned int r=0;r<size;++r)
  137.                 {
  138.                         for(unsigned int c=0;c<size;++c)
  139.                         {
  140.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  141.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  142.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  143.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  144.                         }
  145.                 }
  146.         }

  147.         //灰白色
  148.         if(size==128)
  149.         {
  150.                 osg::Vec4 color(0.5f,0.5f,0.5f,1.0f);
  151.                 for(unsigned int r=0;r<size;++r)
  152.                 {
  153.                         for(unsigned int c=0;c<size;++c)
  154.                         {
  155.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  156.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  157.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  158.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  159.                         }
  160.                 }
  161.         }

  162.         //黑色
  163.         if(size==256)
  164.         {
  165.                 osg::Vec4 color(0.0f,0.0f,0.0f,1.0f);
  166.                 for(unsigned int r=0;r<size;++r)
  167.                 {
  168.                         for(unsigned int c=0;c<size;++c)
  169.                         {
  170.                                 *ptr++ = (unsigned char)((color[0])*255.0f);
  171.                                 *ptr++ = (unsigned char)((color[1])*255.0f);
  172.                                 *ptr++ = (unsigned char)((color[2])*255.0f);
  173.                                 *ptr++ = (unsigned char)((color[3])*255.0f);
  174.                         }
  175.                 }
  176.         }
  177. }

  178. int main()
  179. {
  180.         osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();

  181.         osg::ref_ptr<osg::Group> root = new osg::Group();

  182.         //创建一个平面
  183.         osg::ref_ptr<osg::Geode> geode = createQuad() ;

  184.         osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();

  185.         osg::ref_ptr<osg::Image> image = new osg::Image();

  186.         //创建一个MipmapDataType列表,用来各层图片数据的偏移地址
  187.         osg::Image::MipmapDataType mipmapData;

  188.         //纹理的尺寸的最大值,必须为2的幂次
  189.         unsigned int s = 256;

  190.         //计算所需分配的数组的大小
  191.         unsigned int totalSize = 0;

  192.         for(unsigned int i=0; s>0; s>>=1, ++i)
  193.         {
  194.                 if (i>0)
  195.                 {
  196.                         mipmapData.push_back(totalSize);
  197.                 }

  198.                 totalSize += s*s*4;
  199.         }

  200.         //申请一个数据
  201.         unsigned char* ptr = new unsigned char[totalSize];

  202.         //设置image的尺寸大小,数据及数据格式
  203.         image->setImage(256, 256, 256, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, ptr, osg::Image::USE_NEW_DELETE,1);

  204.         //将偏移地址传入imge对象
  205.         image->setMipmapLevels(mipmapData);

  206.         //向image中填充各层数据
  207.         s=256 ;
  208.         for(unsigned int i=0; s>0; s>>=1, ++i)
  209.         {
  210.                 fillImage(ptr, s);

  211.                 ptr += s*s*4;
  212.         }

  213.         //创建一个二维纹理对象
  214.         osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;
  215.         //设置贴图
  216.         texture->setImage( 0, image.get() );
  217.         //设置边界处理为REPEATE
  218.         texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT);
  219.         texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT);
  220.         //设置滤波
  221.         texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST_MIPMAP_NEAREST);
  222.         texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);
  223.         //启用二维纹理对象
  224.         stateset->setTextureAttributeAndModes( 0, texture.get(), osg::StateAttribute::ON );

  225.         geode->setStateSet(stateset.get());

  226.         root->addChild(geode.get());

  227.         //优化场景数据
  228.         osgUtil::Optimizer optimizer ;
  229.         optimizer.optimize(root.get()) ;

  230.         viewer->setSceneData(root.get());

  231.         viewer->realize();

  232.         viewer->run();

  233.         return 0 ;
  234. }

复制代码

该用户从未签到

 楼主| 发表于 2010-8-19 12:36:06 | 显示全部楼层
5# FlySky

谢谢你的回答,看了你的代码mipmap的问题解决了。
可是最近做类似谷歌地球的这个东西还是没进展。world wind的源码太庞大了,我实在没有能力在短期内一个人看完。。。。。。


请教您一些问题:
1. 我用osgsimulation例子里面的createEarth函数生成了一个地球(代码如下)。
我现在有银川地区的高清卫星图片(大小为几十兆),怎么把它按照银川的坐标贴到地球上呢? 图片是jpg格式的,一起下下来的还有一个jgw文件。不知道该怎么利用这些东西。


2. 看到以前您回复别人的帖子,对于大图片建议要分成小的切片。于是我把这张图片分成了很多256*256的小图片。可是接下来该怎么往地球上贴呢?

3. osgearth会不会让我的工作简化呢?


osg::Node* createEarth()
{
    osg::TessellationHints* hints = new osg::TessellationHints;
    hints->setDetailRatio(5.0f);
   
    osg::ShapeDrawable* sd = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0,0.0,0.0), osg::WGS_84_RADIUS_POLAR), hints);
   
    osg::Geode* geode = new osg::Geode;
    geode->addDrawable(sd);
   
    std::string filename = osgDB::findDataFile("Images/land_shallow_topo_2048.jpg");
    geode->getOrCreateStateSet()->setTextureAttributeAndModes(0, new osg::Texture2D(osgDB::readImageFile(filename)));
   
    osg::CoordinateSystemNode* csn = new osg::CoordinateSystemNode;
    csn->setEllipsoidModel(new osg::EllipsoidModel());
    csn->addChild(geode);
   
    return csn;
   
}


期待您的回复!

该用户从未签到

发表于 2011-4-2 10:27:29 | 显示全部楼层
我也想做这个 应该怎么做呢?

该用户从未签到

发表于 2011-8-8 13:39:58 | 显示全部楼层
正在研究!
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表