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

下面的示例,通过一个纹理坐标生成器(继承自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+动态纹理坐标

    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超级宝典总结(二)2D/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. JavaWeb基础—会话管理之Cookie

    一.什么是会话 打开浏览器,浏览各种资源,点击各种超链接,直至关闭浏览器,整个过程称为会话 二.会话管理的两种技术 1.Cookie 基于客户端.在客户端记录信息来确认用户身份.以cookie的形式写 ...

  2. 20145209刘一阳《JAVA程序设计》课堂测试总结

    20145209刘一阳<JAVA程序设计>课堂测试总结 这次重新学习JAVA这门课,我对本学期没有参与的测试进行了总结并制作成二维码方便老师检查,详细内容如下: 第一周课堂测试### ht ...

  3. jQuery学习- 表单事件

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. 从Iris数据集开始---机器学习入门

    代码多来自<Introduction to Machine Learning with Python>. 该文集主要是自己的一个阅读笔记以及一些小思考,小总结. 前言 在开始进行模型训练之 ...

  5. 一维码UPC E简介及其解码实现(zxing-cpp)

    UPC(Universal Product Code)码是最早大规模应用的条码,其特性是一种长度固定.连续性的条  码,目前主要在美国和加拿大使用,由于其应用范围广泛,故又被称万用条码. UPC码仅可 ...

  6. com.jcraft.jsch.JSchException: java.io.FileNotFoundException: file:\D:\development\ideaProjects\salary-card\target\salary-card-0.0.1-SNAPSHOT.jar!\BOOT-INF\classes!\keystore\login_id_rsa 资源未找到

    com.jcraft.jsch.JSchException: java.io.FileNotFoundException: file:\D:\development\ideaProjects\sala ...

  7. 2_C语言中的数据类型 (一)2.1.常量和字符串常量

    2.1 常量就是在程序中不可变化的量,常量在定义的时候必须给一个初值. 1.1.1          #define 定义一个宏常量 1.1.2          const 定义一个const常量 ...

  8. git删除所有提交历史记录

    这种方式是最快最有效的 进项目根目录启动git bash,然后执行这些即可 最后的 git push -f origin master 会失败,直接在idea里push就能成功了 .Checkout ...

  9. JDBC注册驱动的三种方式(MySQL)

    第一种:通过反射Class.forName("com.mysql.jdbc.Driver"); 第二种:通过DriverManage的静态方法DriverManager.regis ...

  10. ITerm常用的快捷键

    新建标签:command + t 关闭标签:command + w 切换标签:command + 数字 或者 command + 左右方向键 切换全屏:command + enter 查找:comma ...