OSG学习:计算纹理坐标
来源:互联网 发布:巴黎住宿攻略 知乎 编辑:程序博客网 时间:2024/05/22 05:28
在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥、圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲。一般而言,曲面表面的曲率越大,纹理所需要的扭曲度就越大。这时,直接指定纹理坐标可能是一件非常困难的事情了。
下面的示例,通过一个纹理坐标生成器(继承自osg::NodeVisitor访问器)遍历模型的所有顶点及法线,然后根据顶点、法线及一定的比例来确定纹理坐标。
#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Geode>#include <osg/Geometry>#include <osg/Group>#include <osg/Camera>#include <osg/MatrixTransform>#include <osg/PositionAttitudeTransform>#include <osg/TexGen>#include <osg/TexEnv>#include <osg/NodeVisitor>#include <osgDB/ReadFile>#include <osgDB/WriteFile>#include <osgUtil/Optimizer>#include <iostream>//纹理坐标生成器,继承自NodeVisitorclass TexCoordGenerator: public osg::NodeVisitor {public: //遍历所有的子节点 TexCoordGenerator(): NodeVisitor(NodeVisitor::TRAVERSE_ALL_CHILDREN) { // } void apply(osg::Geode& geode) { //通过包围盒来确定合适的比例 const osg::BoundingSphere &bsphere = geode.getBound(); float scale = 10; if (bsphere.radius() != 0) { scale = 5 / bsphere.radius(); } //遍历所有几何体,并设置纹理坐标 for (unsigned i=0; i<geode.getNumDrawables(); ++i) { osg::Geometry* geo = dynamic_cast<osg::Geometry* >(geode.getDrawable(i)); if (geo) { osg::Vec2Array* tc = generate_coords(geo->getVertexArray(), geo->getNormalArray(), scale); geo->setTexCoordArray(0, tc); } } NodeVisitor::apply(geode); }protected: //计算纹理坐标 osg::Vec2Array* generate_coords(osg::Array* vx, osg::Array* nx, float scale) { osg::Vec2Array* v2a = dynamic_cast<osg::Vec2Array*>(vx); osg::Vec3Array* v3a = dynamic_cast<osg::Vec3Array*>(vx); osg::Vec4Array* v4a = dynamic_cast<osg::Vec4Array*>(vx); osg::Vec2Array* n2a = dynamic_cast<osg::Vec2Array*>(nx); osg::Vec3Array* n3a = dynamic_cast<osg::Vec3Array*>(nx); osg::Vec4Array* n4a = dynamic_cast<osg::Vec4Array*>(nx); osg::ref_ptr<osg::Vec2Array> tc = new osg::Vec2Array; for (unsigned i=0; i<vx->getNumElements(); ++i) { osg::Vec3 P; if (v2a) P.set((*v2a)[i].x(), (*v2a)[i].y(), 0); if (v3a) P.set((*v3a)[i].x(), (*v3a)[i].y(), (*v3a)[i].z()); if (v4a) P.set((*v4a)[i].x(), (*v4a)[i].y(), (*v4a)[i].z()); osg::Vec3 N(0, 0, 1); if (n2a) N.set((*n2a)[i].x(), (*n2a)[i].y(), 0); if (n3a) N.set((*n3a)[i].x(), (*n3a)[i].y(), (*n3a)[i].z()); if (n4a) N.set((*n4a)[i].x(), (*n4a)[i].y(), (*n4a)[i].z()); int axis = 0; if (N.y() > N.x() && N.y() > N.z()) axis = 1; if (-N.y() > N.x() && -N.y() > N.z()) axis = 1; if (N.z() > N.x() && N.z() > N.y()) axis = 2; if (-N.z() > N.x() && -N.z() > N.y()) axis = 2; osg::Vec2 uv; switch (axis) { case 0: uv.set(P.y(), P.z()); break; case 1: uv.set(P.x(), P.z()); break; case 2: uv.set(P.x(), P.y()); break; default: ; } tc->push_back(uv * scale); } return tc.release(); }};//创建二维纹理状态对象osg::ref_ptr<osg::StateSet> createTexture2DState(osg::ref_ptr<osg::Image> image){ //创建状态集对象 osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet(); //创建二维纹理对象 osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D(); texture->setDataVariance(osg::Object::DYNAMIC); //设置贴图 texture->setImage(image.get()); texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_LINEAR); texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); texture->setWrap(osg::Texture::WRAP_S, osg::Texture::REPEAT); texture->setWrap(osg::Texture::WRAP_T, osg::Texture::REPEAT); stateset->setTextureAttributeAndModes(0,texture.get(),osg::StateAttribute::ON); return stateset.get() ;}int main(){ osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer(); osg::ref_ptr<osg::Group> root = new osg::Group(); //读取贴图文件 osg::ref_ptr<osg::Image> image = osgDB::readImageFile("Images/primitives.gif"); osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("dumptruck.osg"); //计算纹理坐标 TexCoordGenerator tcg ; node->accept(tcg); //创建状态集对象 osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet(); stateset = createTexture2DState(image.get()); //使用二维纹理 node->setStateSet(stateset.get()); root->addChild(node.get()); //优化场景数据 osgUtil::Optimizer optimizer ; optimizer.optimize(root.get()) ; viewer->setSceneData(root.get()); viewer->realize(); viewer->run(); return 0 ;}
阅读全文
0 0
- OSG学习:计算纹理坐标
- OSG学习:多重纹理映射
- 纹理坐标的计算方式
- 两种提取OSG中纹理坐标的方法
- OSG 学习第四天:自动生成纹理
- OpenGL自动计算顶点纹理坐标
- OpenGL学习二十一:纹理坐标
- 纹理坐标
- 纹理坐标
- 纹理坐标
- 纹理坐标
- 纹理坐标
- 纹理坐标
- osg for android 学习之十四:再说纹理
- osg for android 学习之纹理丢失解决
- osg纹理动画效果
- OSG:4.纹理贴图
- OpenGL、OSG纹理
- QT QML自定义等待提示框
- Jmeter运行报警告信息
- Linux 安装 Eclipse
- lambda函数
- 从mysql中将数据表复制给hbase
- OSG学习:计算纹理坐标
- 算法2:树的带权路径长度(创新工场)
- vuex学习六----actions
- android自定义跑马灯
- Xtrabackup2.3.6 安装
- 博客积分
- linux shell编程
- HDU 4765 Tsp 2013长春网络赛G题 DP
- Spring:IoC 用法(八、<bean>用法)