OSG学习:计算纹理坐标

时间:2022-09-28 08:25:18

在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥、圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲。一般而言,曲面表面的曲率越大,纹理所需要的扭曲度就越大。这时,直接指定纹理坐标可能是一件非常困难的事情了。

下面的示例,通过一个纹理坐标生成器(继承自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> //纹理坐标生成器,继承自NodeVisitor
class 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 ;
}

OSG学习:计算纹理坐标的更多相关文章

  1. osg使用shader动态修改纹理坐标

    #include <osg/Node> #include <osg/Geometry> #include <osg/Notify> #include <osg ...

  2. OSG绘制金字塔geode&plus;动态纹理坐标

    osg::Node* createPyramidModel() { // create the root node which will hold the model. osg::Group* roo ...

  3. WebGL学习之纹理贴图

    为了使图形能获得接近于真实物体的材质效果,一般会使用贴图,贴图类型主要包括两种:漫反射贴图和镜面高光贴图.其中漫反射贴图可以同时实现漫反射光和环境光的效果. 实际效果请看demo:纹理贴图 2D纹理 ...

  4. WebGL学习之纹理盒

    原文地址:WebGL学习之纹理盒 我们之前已经学习过二维纹理 gl.TEXTURE_2D,而且还使用它实现了各种效果.但还有一种立方体纹理 gl.TEXTURE_CUBE_MAP,它包含了6个纹理代表 ...

  5. OpenGL超级宝典总结&lpar;二&rpar;2D&sol;3D笛卡尔坐标、坐标裁剪、纹理坐标、MVP转换等概念

    如果你想把图形渲染在正确的位置上,那么坐标的设置就很重要了.在OpenGL中,与坐标相关的主要有笛卡尔坐标.坐标裁剪.纹理坐标.MVP(Model View Projection)转换. 1.笛卡尔坐 ...

  6. OSG学习:基本几何体绘制示例

    绘制并渲染几何体主要有如下3大步骤: 1.创建各种向量数据,如顶点.纹理坐标.颜色和法线等.需要注意的是,添加顶点数据时主要按照逆时针顺序添加, 以确保背面剔除的正确. 2.实例化一个几何体对象(os ...

  7. OpenMesh 读写网格控制(读取写入纹理坐标,法向等)

    OpenMesh读取网格默认是不自动读取obj网格中的法向,纹理坐标等信息的,写入网格同样也是.所以要读取(或写入)这些信息需要修改默认的选项. 先看一下其读写网格的函数 template<cl ...

  8. osg学习示例之遇到问题四骨骼动画编译osgCal

    osg学习示例之遇到问题四骨骼动画编译osgCal 转自:http://blog.csdn.net/wuwangrun/article/details/8239451 今天学到书<OpenSce ...

  9. uv纹理坐标设定与贴图规则

    1.什么是UV?   对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV坐标.什么是UV?简单的说,就是贴图影射到模型表面的依据. 完整的说,其实应该是UVW(因为 ...

随机推荐

  1. oracle PL&sol;SQL高级特性

    触发器:存放在数据库中,并被隐含执行的存储过程. 由触发事件,触发条件,触发操作组成. DML触发器:指定触发器时机(before or after),触发事件(insert  , delete, u ...

  2. python web编程 创建一个web服务器

    这里就介绍几个底层的用于创建web服务器的模块,其中最为主要的就是BaseHTTPServer,很多框架和web服务器就是在他们的基础上创建的 基础知识 要建立一个Web 服务,一个基本的服务器和一个 ...

  3. 将数据集做成VOC2007格式用于Faster-RCNN训练

    1.命名 文件夹名VOC2007.图片名六位数字.将数据集相应的替换掉VOC2007中的数据. (Updated development kit, annotated test data )   2. ...

  4. Bootstrap页面布局3 - BS布局以及流动布局

    1. <h1 class='page-header'>布局<small> 使用bootstrap网格系统布局网页</small></h1> 得到如图所示 ...

  5. 挂载nfs系统问题之: Root-NFS&colon; Server returned error -13 while mounting

    今天换了个路由器,由于是自动分的IP,现在的IP和之前的不在同一网段.以前是192.168.0.xxx,现在是192.168.1.xxx.本以为将serverip,ipaddr,bootargs这些参 ...

  6. BZOJ 1708&colon; &lbrack;Usaco2007 Oct&rsqb;Money奶牛的硬币

    1708: [Usaco2007 Oct]Money奶牛的硬币 Description 在创立了她们自己的政权之后,奶牛们决定推广新的货币系统.在强烈的叛逆心理的驱使下,她们准备使用奇怪的面值.在传统 ...

  7. ORM框架SQLAlchemy

    SQLAlchemy orm英文全称object relational mapping,就是对象映射关系程序,简单来说就是类似python这种面向对象的程序来说一切皆对象,但是使用的数据库却都是关系型 ...

  8. FileProvider的使用及应用更新时提示:解析包出错、失败等问题

    Android 7.0以上的版本更新采用系统自带的DownloadManager更新 DOWNLOADPATH ="/download/" https://www.jianshu. ...

  9. MySQL参数:innodb&lowbar;flush&lowbar;log&lowbar;at&lowbar;trx&lowbar;commit 和 sync&lowbar;binlog

    innodb_flush_log_at_trx_commit 和 sync_binlog 是 MySQL 的两个配置参数,前者是 InnoDB 引擎特有的.之所以把这两个参数放在一起讨论,是因为在实际 ...

  10. SQL Server如何将Id相同的字段合并,并且以逗号隔开

    需要用到stuff函数: 例: id             name           1               张三           1               李四       ...