osg纯手工画球+贴纹理
手动计算球面顶点的坐标,纹理坐标,来画球并贴纹理
其中createSphereGeom()
函数的的二个参数为18,意思是在经纬度上每10度设一个点,因为经度一共是180度,180/18=10,相当于横着把球分为18份,每一份相当于一个圆盘,然后再把圆盘分为18*2=36份,每一份相当于一个扇形。
由于要贴纹理,所以在实现的时候,最上面的一个顶点是36+1=37个顶点重合了,最下面的一个顶点一样,中间每一圈的最开始的顶点和最后一个顶点重合,每一圈都有36+1=37个顶点,总共有(36+1)*(18+1)=703个顶点。
为什么每一圈是37个顶点而不是36,其实如果不贴纹理就只是画球,那36个顶点就可以了,但是纹理是一张矩形的图片,你要把一个矩形上的每个点映射到球面上,那每一圈就需要多一个点。
如下图,把一张纸分为4份,上面有5个点,再把这张纸卷成圆筒,最左边和最右边的点重合了,看起来就只有4个点了。当然如果不需要贴纹理,那就不用重合的点了。
纹理的坐标原点是在左下角,为了和物体位置的坐标xyz区分,纹理坐标叫做str,s相当于x,t相当y。s是横坐标,t是纵坐标。
下面看完整的代码,想要运行,你需要安装好osg
#include <math.h>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Vec3>
#include <osg/Geometry>
#include <osg/ref_ptr>
#include <osg/Vec2>
#include <osg/Texture2D>
#include <osgDB/ReadFile>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgGA/StateSetManipulator>
/**
@brief : 创建一个球的几何节点
@param : [in] dRadius 球的半径
@param : [in] iHint 每180/iHint度设置一个点,默认18
@return: 一个球的osg::Geometry*
*/
osg::Geometry* createSphereGeom(double dRadius = 1., int iHint = 18)
{
osg::ref_ptr<osg::Geometry> rpGeom = new osg::Geometry;
osg::ref_ptr<osg::Vec3Array> rpVertexes = new osg::Vec3Array;//顶点数组
osg::ref_ptr<osg::Vec3Array> rpNormal = new osg::Vec3Array;//法线数组
osg::ref_ptr<osg::Vec2Array> rpTexCoord = new osg::Vec2Array;//纹理数组
for (int i = 0; i <= iHint; i++)//从上到下添加点,有等于号是为了之后贴纹理时可以和图片的点一一对应
{
for (int j = 0; j <= iHint * 2; j++)//逆时针添加点
{
osg::Vec3 vec3VertexT(
sin(osg::PI*i / iHint)*cos(osg::PI*j / iHint),
sin(osg::PI*i / iHint)*sin(osg::PI*j / iHint),
cos(osg::PI*i / iHint));//球面坐标公式
rpVertexes->push_back(vec3VertexT * dRadius);//添加顶点
rpNormal->push_back(vec3VertexT);//添加法线
rpTexCoord->push_back(osg::Vec2(double(j) / 2.0 / iHint
, 1 - double(i) / iHint));//添加纹理坐标
}
}
osg::ref_ptr<osg::Vec4Array> rpColors = new osg::Vec4Array;
rpColors->push_back(osg::Vec4(1.0, 1.0, 1.0, 1.0));
rpGeom->setVertexArray(rpVertexes);
rpGeom->setNormalArray(rpNormal);
rpGeom->setNormalBinding(osg::Geometry::BIND_PER_VERTEX);
rpGeom->setColorArray(rpColors);
rpGeom->setColorBinding(osg::Geometry::BIND_OVERALL);
rpGeom->setTexCoordArray(0, rpTexCoord);
//添加图元
osg::ref_ptr<osg::DrawElementsUInt> rpFace = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP);
for (int i = 0; i < iHint; i++) {
for (int j = 0; j <= iHint * 2; j++) {
rpFace->push_back(i*(iHint * 2 + 1) + j);
rpFace->push_back((i + 1)*(iHint * 2 + 1) + j);
}
}
rpGeom->addPrimitiveSet(rpFace);
return rpGeom.release();
}
/**
@brief : 给球贴纹理
@param : [in/out] pNode 球的节点
@return:
*/
void setTex(osg::Node* pNode)
{
osg::ref_ptr<osg::Image> rpImage = osgDB::readImageFile("../star/moon.jpg");
osg::ref_ptr<osg::Texture2D> rpTexture = new osg::Texture2D();
rpTexture->setImage(rpImage);
rpTexture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);//设置S方向的环绕模式
rpTexture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);//设置R方向的环绕模式
//rpTextureT->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);
//rpTextureT->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
osg::ref_ptr<osg::StateSet> pState = pNode->getOrCreateStateSet();
pState->setTextureAttributeAndModes(0, rpTexture, osg::StateAttribute::ON);
}
int main(int argc, char** argv)
{
osg::ref_ptr<osgViewer::Viewer> rpViewer = new osgViewer::Viewer();
osg::ref_ptr<osg::Group> rpRoot = new osg::Group();
osg::ref_ptr<osg::Geode> rpGeode = new osg::Geode;
rpGeode->addChild(createSphereGeom(1., 45));
setTex(rpGeode);//在球上贴纹理
rpRoot->addChild(rpGeode);
rpViewer->setSceneData(rpRoot);
rpViewer->addEventHandler(new osgGA::StateSetManipulator(rpViewer->getCamera()->getOrCreateStateSet()));//添加w事件处理
rpViewer->addEventHandler(new osgViewer::StatsHandler);//添加s事件处理
rpViewer->run();
return 0;
}
程序运行截图
未贴纹理的球:
隐藏表面,只显示线的球,即按w键后的球:
只显示点的球:
osg纯手工画球+贴纹理的更多相关文章
- HTML5+CSS3+Jquery实现纯手工的垂直时光轴【附源码】
前言 由于工作中需要,系统中需要记录不同时间发生的事件,为了提升用户体验,决定用时光轴来实现.[据说这个东西挺火的,QQ空间和FB都在用...] 这个时光轴是在 三生石上 这位博主的时光轴基础上修改的 ...
- 用纯css画个三角形
用纯css画个三角形以下是源代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" " ...
- 纯手工打造漂亮的瀑布流,五大插件一个都不少Bootstrap+jQuery+Masonry+imagesLoaded+Lightbox!
前两天写的文章<纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!>受到很多网友的喜爱,今天特别推出姊妹篇<纯手工打造漂亮的瀑 ...
- 纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!
前言 FineUI控件库发展至今已经有 5 个年头,目前论坛注册的QQ会员 5000 多人,捐赠用户 500 多人(捐赠用户转化率达到10%以上,在国内开源领域相信这是一个梦幻数字!也足以证明Fine ...
- JAVA+PHP+阿里云组件纯手工实现POP、SMTP、IMAP开发邮件服务器(二)
java开发邮件服务器的接收模块 用java建立socket服务端,监听端口25,实现SMTP协议.即可完成邮件服务器的接收模块. 这里要注意的是,SMTP协议其实可以分为两种.一种是你用手机.PC等 ...
- [置顶] 纯手工打造漂亮的瀑布流,五大插件一个都不少Bootstrap+jQuery+Masonry+imagesLoaded+Lightbox!
前两天写的文章<纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!>受到很多网友的喜爱,今天特别推出姊妹篇<纯手工打造漂亮的瀑 ...
- [置顶] 纯手工打造漂亮的垂直时间轴,使用最简单的HTML+CSS+JQUERY完成100个版本更新记录的华丽转身!
前言 FineUI控件库发展至今已经有 5 个年头,目前论坛注册的QQ会员 5000 多人,捐赠用户 500 多人(捐赠用户转化率达到10%以上,在国内开源领域相信这是一个梦幻数字!也足以证明Fine ...
- 【转】纯手工玩转 Nginx 日志
Nginx 日志对于大部分人来说是个未被发掘的宝藏,总结之前做某日志分析系统的经验,和大家分享一下 Nginx 日志的纯手工分析方式. Nginx 日志相关配置有 2 个地方:access_log 和 ...
- 纯手工编写的PE可执行程序
[文章标题]: 纯手工编写的PE可执行程序[文章作者]: Kinney[下载地址]: 自己搜索下载[使用工具]: C32[操作平台]: win 7[作者声明]: 只是感兴趣,没有其他目的.失误之处敬请 ...
随机推荐
- springBoot高级:自动配置分析,事件监听,启动流程分析,监控,部署
知识点梳理 课堂讲义 02-SpringBoot自动配置-@Conditional使用 Condition是Spring4.0后引入的条件化配置接口,通过实现Condition接口可以完成有条件的加载 ...
- 我叫小M,立志建立MySQL帝国。
我是小M,我在卡拉巴拉星球. 我喜欢数据,我立志成为一个数据管理者. 所以我来 Y 公司应聘,听说他们的数据量挺大的. 面试过程还是挺简单的. 我用 007 这三个数字就轻易打败了一堆吹嘘 996 的 ...
- OAuth2.0理解和用法
现在网络的资料到处都是,很容易搜索到自己想要的答案.但答案通常只能解决自己一部分的问题.如果自己想要有一套自己的解决方案,还得重新撸一遍靠谱. 我需要学下OAuth2.0吗? 没看之前以为OAuth2 ...
- Dynamic Programming 动态规划入门笔记
算法导论笔记 programming 指的是一种表格法,并非编写计算机程序 动态规划与分治方法相似,都是通过组合子问题的解来求解原问题.但是分治法将问题划分为互不相交的子问题.而动态规划是应用与子问题 ...
- pytorch从入门到放弃(目录)
目录 前置基础 Pytorch从入门到放弃 推荐阅读 前置基础 Python从入门到放弃(目录) 人工智能(目录) Pytorch从入门到放弃 01_pytorch和tensorflow的区别 02_ ...
- 【Android实习】20场面试斩获大厂offer,我学会了什么
前言 很高兴遇见你~ 先说一下笔者春招实习的情况:从三月初到四月半,经历了近20场面试,一共面试了五家企业,通过了腾讯.字节.蚂蚁.美团的面试,虎牙在一面之后拒了二面邀请. 金三银四,笔者不是在面试中 ...
- Spring 学习笔记(四):Spring AOP
1 概述 本文主要讲述了AOP的基本概念以及在Spring中AOP的几种实现方式. 2 AOP AOP,即Aspect-Oriented Programming,面向切面编程,与OOP相辅相成.类似的 ...
- 关于 下载 nfs-utils时的 gssproxy conflicts with selinux-policy-3.13.1-102.el7.noarch 错误
使用 yum install nfs-utils -y 时 出现如下错误: 错误:gssproxy conflicts with selinux-policy-3.13.1-102.el7.noarc ...
- (十七)VMware Harbor 垃圾清理
1. 在线垃圾清理 注意:从Harbor中删除镜像时不释放空间,垃圾收集是通过从清单中不再引用文件系统中删除blob来释放空间的任务. 注意:在执行垃圾收集时,Harbor将进入只读模式,并且禁止对d ...
- 击鼓传花联想到了Java设计模式:责任链模式
目录 应用场景 简单示例 责任链模式 定义 意图 主要解决问题 何时使用 优缺点 击鼓传花的故事 应用场景 http web请求处理,请求过来后将经过转码.解析.参数封装.鉴权等一系列的处理(责任), ...