OpenSceneGraph 笔记--如何导出三角形数据

转载:http://blog.csdn.net/pizi0475/article/details/5384389

在OpenSceneGraph开发中,为了方便会经常使用到一些不是三角形片的数据,比如四边形等数据。例如画一个管子用四边形带比用三角形片好计算得多。比如现在我们要画一个由两个平面组成的面,我可以这样做:

    osg::Geode* geode=new osg::Geode;
    osg::Geometry* polyGeom = new osg::Geometry;
    osg::Vec3 myCoords[]=
    {
        osg::Vec3(0,1,0),
        osg::Vec3(0,0,0),
        osg::Vec3(1,1,0),
        osg::Vec3(1,0,0),
        osg::Vec3(2,1,0),
        osg::Vec3(2,0,0)
    };

int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
    osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
    polyGeom->setVertexArray(vertices);
    polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,numCoords));
    geode->addDrawable(polyGeom);

这样就用6个点,用OpenGL提供的QUAD_STRIP方式画出了两个平面。
但是如果要把这个平面用于碰撞检测等技术,那么就需要把这六个点所表示的四边形带转换成三角形片才行。这些三角形定点如下:
0 1 0
0 0 0
1 1 0

0 0 0
1 0 0
1 1 0

1 1 0
1 0 0
2 1 0

1 0 0
2 0 0
2 1 0
可以看出两个平面由4个三角形组成,而且都是逆时针排列(朝向一致)。
以前我自己做过转换,但是感觉很麻烦。OpenSceneGraph的Example osggeometry中提供了一个printTriangles函数,它可以打印出一个drawable所有的三角形片,不管最初的数据结构如何:

struct NormalPrint
{
    void operator() (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool) const 
    {
        osg::Vec3 normal = (v2-v1)^(v3-v2);
        normal.normalize();
        std::cout << "/t("<<v1<<") ("<<v2<<") ("<<v3<<") "<<") normal ("<<normal<<")"<<std::endl;
    }
};

// decompose Drawable primtives into triangles, print out these triangles and computed normals.
void printTriangles(const std::string& name, osg::Drawable& drawable)
{
    std::cout<<name<<std::endl;
    
    osg::TriangleFunctor<NormalPrint> tf;
    drawable.accept(tf);
 
    std::cout<<std::endl;
}

核心的思想就是利用osg::TriangleFunctor这个模版。这个模版会让你重载()运算符,然后让Drawable去visit它。在这个过程中,所有原始的数据(不管是三角形片的,还是四边形的)都转换成了三角形片数据。
那么如何把三角形数据导出哪?只需要修改一下借助这个思路,将NormalPrint修改成我们需要的就对了。

struct GetVertex
{
    void operator() (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool) const 
    {
        vertexList->push_back(v1);
        vertexList->push_back(v2);
        vertexList->push_back(v3);
    }

osg::Vec3Array* vertexList;
    
};

void getTriangles(osg::Drawable& drawable)
{
    osg::TriangleFunctor<GetVertex> tf;
    tf.vertexList=new osg::Vec3Array;

drawable.accept(tf);

for(osg::Vec3Array::iterator itr=tf.vertexList->begin();
        itr!=tf.vertexList->end();
        itr++)
    {
        osg::Vec3 vertex=*itr;
        std::cout<<vertex<<std::endl;
    }

std::cout<<std::endl;
}

以下是完整的示例文件:

// PrimitiveSet.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>

struct GetVertex
{
    void operator() (const osg::Vec3& v1,const osg::Vec3& v2,const osg::Vec3& v3, bool) const 
    {
        vertexList->push_back(v1);
        vertexList->push_back(v2);
        vertexList->push_back(v3);
    }

osg::Vec3Array* vertexList;
    
};

void getTriangles(osg::Drawable& drawable)
{
    osg::TriangleFunctor<GetVertex> tf;
    tf.vertexList=new osg::Vec3Array;

drawable.accept(tf);

for(osg::Vec3Array::iterator itr=tf.vertexList->begin();
        itr!=tf.vertexList->end();
        itr++)
    {
        osg::Vec3 vertex=*itr;
        std::cout<<vertex<<std::endl;
    }

std::cout<<std::endl;
}

osg::Node* createGeode()
{
    osg::Geode* geode=new osg::Geode;
    osg::Geometry* polyGeom = new osg::Geometry;
    osg::Vec3 myCoords[]=
    {
        osg::Vec3(0,1,0),
        osg::Vec3(0,0,0),
        osg::Vec3(1,1,0),
        osg::Vec3(1,0,0),
        osg::Vec3(2,1,0),
        osg::Vec3(2,0,0)
    };

int numCoords = sizeof(myCoords)/sizeof(osg::Vec3);
    osg::Vec3Array* vertices = new osg::Vec3Array(numCoords,myCoords);
    polyGeom->setVertexArray(vertices);
    polyGeom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,numCoords));
    geode->addDrawable(polyGeom);
    getTriangles(*polyGeom);
    return geode;
}

int _tmain(int argc, _TCHAR* argv[])
{
    //Set up viewer
    osgViewer::Viewer viewer;
    osg::ref_ptr<osg::GraphicsContext::Traits> traits=new osg::GraphicsContext::Traits;
    traits->x=200;
    traits->y=200;
    traits->width=800;
    traits->height=600;
    traits->windowDecoration=true;
    traits->doubleBuffer=true;
    traits->sharedContext=0;
    
    osg::ref_ptr<osg::GraphicsContext> gc=osg::GraphicsContext::createGraphicsContext(traits.get());
    osg::ref_ptr<osg::Camera> camera=new osg::Camera;
    //osg::Camera camera=new osg::Camera;
    camera->setGraphicsContext(gc.get());
    camera->setViewport(new osg::Viewport(0,0,traits->width,traits->height));
    camera->setDrawBuffer(GL_BACK);
    camera->setReadBuffer(GL_BACK);
    osgGA::TrackballManipulator* tm=new osgGA::TrackballManipulator;
    
    viewer.setCameraManipulator(tm);
    
    viewer.addSlave(camera.get());

//Set up root node
    osg::ref_ptr<osg::Group> root=new osg::Group;

root->addChild(createGeode());

//Start show!
    viewer.setSceneData(root.get());
    viewer.realize();

while(!viewer.done())
    {
        viewer.frame();
    }
}

0
0

OpenSceneGraph 笔记--如何导出三角形数据的更多相关文章

  1. matlab学习笔记4--导入和导出Internet数据

    一起来学matlab-matlab学习笔记4 数据导入和导出_4 导入和导出Internet数据 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合 ...

  2. matlab学习笔记4--导入和导出电子数据表

    一起来学matlab-matlab学习笔记4 数据导入和导出_3 导入和导出电子数据表 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考书籍 <matlab 程序设计与综合应用> ...

  3. R学习笔记(4): 使用外部数据

    来源于:R学习笔记(4): 使用外部数据 博客:心内求法 鉴于内存的非持久性和容量限制,一个有效的数据处理工具必须能够使用外部数据:能够从外部获取大量的数据,也能够将处理结果保存.R中提供了一系列的函 ...

  4. SpringBoot图文教程10—模板导出|百万数据Excel导出|图片导出「easypoi」

    有天上飞的概念,就要有落地的实现 概念十遍不如代码一遍,朋友,希望你把文中所有的代码案例都敲一遍 先赞后看,养成习惯 SpringBoot 图文教程系列文章目录 SpringBoot图文教程1「概念+ ...

  5. 【Telerik】<telerik:RadComboBox>导出列表数据

    近来在做项目,做到导出功能.使用<telerik:RadComboBox>的下拉框来实现导出部分或导出所有数据的功能.

  6. 使用BCP导出导入数据

    bcp 实用工具可以在 Microsoft SQL Server 实例和用户指定格式的数据文件间大容量复制数据. 使用 bcp 实用工具可以将大量新行导入 SQL Server 表,或将表数据导出到数 ...

  7. mysqldump导出部分数据的方法: 加入--where参数

    mysqldump导出部分数据的方法: 加入--where参数 mysqldump -u用户名 -p密码 数据库名 表名 --where="筛选条件" > 导出文件路径 my ...

  8. linux下导入、导出mysql数据库命令 下载文件到本地

    一.下载到本地 yum install lrzsz sz filename  下载 rz filename  上传   linux下导入.导出mysql数据库命令 一.导出数据库用mysqldump命 ...

  9. phpmyadmin导入导出大数据文件的办法

    在phpmyadmin的使用中,经常需要进行导入导出数据库的操作. 但是在导入导出大型数据库文件的时候经常会只是部分导出或者部分导入. 或者是导入导出不成功. 原因就是服务器和php.mysql限制了 ...

随机推荐

  1. 【openStack】Libcloud 如何支持 keystone V3?

    Examples This section includes some examples which show how to use the newly available functionality ...

  2. 【iBeacon】iBeacon前沿初探技术备忘

    iBeacon是工作在蓝牙4.0(BLE)硬件下的一种协议,属于蓝牙4.0广播协议的一种,通过该协议和一个蓝牙模块可以实现非接触的身份识别.位置检测等. How does BLE communicat ...

  3. 第一章 简单工厂模式 及 UML中类图的表示方法

    写一个简单计算器程序时,可以写一个操作类,然后加.减.乘.除操作分别继承它,复写操作计算结果的方法.写一个简单工厂类,通过输入的操作符,使用操作类来new一个相应的操作类的子类对象.这样,工厂就实例化 ...

  4. yii小细节

    1.main.php增加导航栏严格区分大小写,否则会出现404错误 2.增加'分页'功能---前后台的models里面的search.php 添加 public function search($pa ...

  5. 【python】安装指定模块

    使用pip 1.卸载模块 sudo pip uninstall xxx 2.安装指定版本模块 sudo pip install xxx==2.0.1.3

  6. 二维码跳转不同的 app store

    说道二维码 之前是用来跳转app store  然后在就是出来的 扫码付款什么的 用的很平常,其实里面也很简单   自己刚开始接触的时候     同事说要做一个二维码下载 应用 => 我=懵逼 ...

  7. $stateProvider

    在你的应用中大多数状态都有与其相关联的 url,路由控制不是设计完成 state 之后的事后想法,而是开始开发时就应该考虑的问题. 这里是如何设置一个基本url. 12345 $stateProvid ...

  8. 分布式之ZookeeperMac安装

    Zookeeper用于分布式计算中的协调员,观察员,观察者,分布式锁,在系统中利用Zookeeper来处理事件通知,队列,锁等功能. 使用brew安装 zookeeper. 可参考:http://bl ...

  9. BMW

    tc金游世界单登陆允许服务 tc金游世界注册机允许服务 tc金游辅助智能游戏清分允许服务[智能游戏] tc金游辅助挂机王清分允许服务[游辅助挂机清分] tc金游世界王自动打牌允许服务[自动打牌] tc ...

  10. Js动态设置rem来实现移动端字体的自适应

    //设置根元素字体 var win = window, doc = document; function setFontSize() { var winWidth = $(window).width( ...