OSG学习:计算纹理坐标
在很多时候,直接指定纹理坐标是非常不方便的,如曲面纹理坐标,只有少数的曲面(如圆锥、圆柱等)可以在不产生扭曲的情况下映射到平面上,其他的曲面在映射到表面时都会产生一定程度的扭曲。一般而言,曲面表面的曲率越大,纹理所需要的扭曲度就越大。这时,直接指定纹理坐标可能是一件非常困难的事情了。
下面的示例,通过一个纹理坐标生成器(继承自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学习:计算纹理坐标的更多相关文章
- osg使用shader动态修改纹理坐标
#include <osg/Node> #include <osg/Geometry> #include <osg/Notify> #include <osg ...
- OSG绘制金字塔geode+动态纹理坐标
osg::Node* createPyramidModel() { // create the root node which will hold the model. osg::Group* roo ...
- WebGL学习之纹理贴图
为了使图形能获得接近于真实物体的材质效果,一般会使用贴图,贴图类型主要包括两种:漫反射贴图和镜面高光贴图.其中漫反射贴图可以同时实现漫反射光和环境光的效果. 实际效果请看demo:纹理贴图 2D纹理 ...
- WebGL学习之纹理盒
原文地址:WebGL学习之纹理盒 我们之前已经学习过二维纹理 gl.TEXTURE_2D,而且还使用它实现了各种效果.但还有一种立方体纹理 gl.TEXTURE_CUBE_MAP,它包含了6个纹理代表 ...
- OpenGL超级宝典总结(二)2D/3D笛卡尔坐标、坐标裁剪、纹理坐标、MVP转换等概念
如果你想把图形渲染在正确的位置上,那么坐标的设置就很重要了.在OpenGL中,与坐标相关的主要有笛卡尔坐标.坐标裁剪.纹理坐标.MVP(Model View Projection)转换. 1.笛卡尔坐 ...
- OSG学习:基本几何体绘制示例
绘制并渲染几何体主要有如下3大步骤: 1.创建各种向量数据,如顶点.纹理坐标.颜色和法线等.需要注意的是,添加顶点数据时主要按照逆时针顺序添加, 以确保背面剔除的正确. 2.实例化一个几何体对象(os ...
- OpenMesh 读写网格控制(读取写入纹理坐标,法向等)
OpenMesh读取网格默认是不自动读取obj网格中的法向,纹理坐标等信息的,写入网格同样也是.所以要读取(或写入)这些信息需要修改默认的选项. 先看一下其读写网格的函数 template<cl ...
- osg学习示例之遇到问题四骨骼动画编译osgCal
osg学习示例之遇到问题四骨骼动画编译osgCal 转自:http://blog.csdn.net/wuwangrun/article/details/8239451 今天学到书<OpenSce ...
- uv纹理坐标设定与贴图规则
1.什么是UV? 对于三维模型,有两个最重要的坐标系统,一是顶点的位置(X,Y,Z)坐标,另一个就是UV坐标.什么是UV?简单的说,就是贴图影射到模型表面的依据. 完整的说,其实应该是UVW(因为 ...
随机推荐
- 【转载】WCF 客户端识别认证之UserName认证
原文地址: http://blog.csdn.net/zxz414644665/article/details/9308055 过程:用户调用service,服务端验证用户传来的用户名和密码(传输过程 ...
- # 2017-2018-1 20155224 加分项-实现mypwd
2017-2018-1 20155224 加分项-实现mypwd 1. 学习pwd命令 pwd命令以绝对路径的方式显示用户当前工作目录.命令将当前目录的全路径名称(从根目录)写入标准输出.全部目录使用 ...
- 4 伪ajax:jsonp、cors 跨域请求
一.同源策略 https://www.cnblogs.com/yuanchenqi/articles/7638956.html 同源策略(Same origin policy)是一种约定,它是浏览器最 ...
- python之shutil模块详解
shutil模块 -- --High-level file operations 高级的文件操作模块. os模块提供了对目录或者文件的新建/删除/查看文件属性,还提供了对文件以及目录的路径操作.比如 ...
- JavaScript 的HTML转义方法 html_encode 和 html_decode
此方法用来将用户输入内容中的尖括号.引号等进行转义
- sqlite3 数据库命令操作
SQLite 数据库,是一个非常轻量级自包含(lightweight and self-contained)的DBMS,它可移植性好,很容易使用,很小,高效而且可靠. SQLite嵌入到使用它的应用程 ...
- spring cloud网关通过Zuul RateLimit 限流配置
目录 引入依赖 配置信息 RateLimit源码简单分析 RateLimit详细的配置信息解读 在平常项目中为了防止一些没有token访问的API被大量无限的调用,需要对一些服务进行API限流.就好比 ...
- c语言数字图像处理(六):二维离散傅里叶变换
基础知识 复数表示 C = R + jI 极坐标:C = |C|(cosθ + jsinθ) 欧拉公式:C = |C|ejθ 有关更多的时域与复频域的知识可以学习复变函数与积分变换,本篇文章只给出DF ...
- OpenCV中图像以Mat类型保存时各通道数据在内存中的组织形式及python代码访问各通道数据的简要方式
以最简单的4 x 5三通道图像为例,其在内存中Mat类型的数据组织形式如下: 每一行的每一列像素的三个通道数据组成一个一维数组,一行像素组成一个二维数组,整幅图像组成一个三维数组,即: Mat.dat ...
- vue处理循环列表动态数据问题
调用方法:Vue.set( target, key, value ) target:要更改的数据源(可以是对象或者数组) key:要更改的具体数据 value :重新赋的值 <!DOCTYPE ...