OSG::Quat(四元数)用法

本文介绍了如何利用osg::Quat对象设置节点或一组节点的姿态。详细解释了两种构造函数的用法,包括如何创建单轴或多轴旋转,并提供了角度转换为弧度的实用方法。

转自:http://blog.163.com/dj_zone/blog/static/4908931320098294047820/

osg::Quat

To set the attitude of a node or group of nodes, we use a new object, the osg::Quat. An osg::Quat is used to instantiate a quaternion, which we use to rotate objects. The two functions that we will use to apply rotation transformations to a PAT node are:

void setAttitude(const Quat& quat);
const Quat& getAttitude() const;

We simply construct a new osg::Quat whenever we want to rotate a PAT. The two declarations for an osg::Quat are:

osg::Quat(value_type angle, const Vec3d &axis)
osg::Quat(value_type angle1, const Vec3d& axis1, value_type angle2, const Vec3d& axis2, value_type angle3, const Vec3d& axis3)

The first constructor creates a osg::Quat with a facing of angle in radians around one or more axes defined within the osg::Vec3d. For example:

osg::Quat(1.2, osg::Vec3d(1.0, 0.0, 1.0));

This will create a quaternion that has the properties of rotating 1.2 radians around the x and z axis. For the axis, a value of 1.0 will represent a rotation around that axis, with a value of 0.0 producing no rotation. Also note that because there is but a single angle of rotation, all the axes will be rotated by the same amount if they are flagged for rotation. That is, with this constructor, I cannot rotate 3.0 radians around the x axis and 4.0 radians around the y axis. That requires a more complicated system where there is an individual angle for each axis. For example:

osg::Quat(
    1.0, osg::Vec3d(1.0, 0.0, 0.0),
    2.0, osg::Vec3d(0.0, 1.0, 0.0),
    0.0, osg::Vec3d(0.0, 0.0, 1.0)
);

This constructor is used when the angle of rotation around more than one axis should not be equal. In the above example, we rotate 1.0 radians around the x axis, 2.0 around the y, and 0.0 around the z.

I find it easier to use degrees rather than radians, and OSG helps with degree usage by offering the following function to convert degrees into radians:

osg::DegreesToRadians(<some_degree_value>);

The osg::DegreesToRadians function returns a double. Note that, like translations, rotation angles are offsets from initial values, so unless we keep increasing or changing the rotational angle, the object will not rotate. Setting the attitude of a PAT with the Quat of (5.0, (1.0, 0.0, 0.0)) will NOT rotate the object 5 units per iteration around the x axis. Instead it will rotate the object 5 radians around the x axis on first call, and it will stay that way until the angle is changed.

给你一个函数实现代码,函数中生成顶面圆环的部分,三角形顶点绕行顺序是顺时针,怎么修改为逆时针呢?static osg::Geometry* createCircleBottleWithTopHole(const std::vector<double>& radiuses, const std::vector<osg::Vec3d>& centers, double topHoleRadius) { double deltaAngle = osg::PI * 2.0 / 12; osg::Quat rot; rot.makeRotate(deltaAngle, osg::Vec3d(0, 0, 1)); osg::ref_ptr<osg::Vec3Array> va = new osg::Vec3Array; osg::ref_ptr<osg::Vec3Array> na = new osg::Vec3Array; osg::ref_ptr<osg::Vec2Array> ta = new osg::Vec2Array; osg::ref_ptr<osg::Geometry> geom = new osg::Geometry; geom->setVertexArray(va); geom->setNormalArray(na, osg::Array::BIND_PER_VERTEX); geom->setTexCoordArray(0, ta); osg::Vec3d topC = centers.front(); osg::Vec3d bottomC = centers.back(); double topR = radiuses.front(); // 处理顶部之前的部分 for (size_t i = 1; i < centers.size(); ++i) { double r1 = radiuses[i - 1]; double r2 = radiuses[i]; const osg::Vec3d& c1 = centers[i - 1]; const osg::Vec3d& c2 = centers[i]; float tcy1 = (centers[i - 1].z() - bottomC.z()) * 0.6; float tcy2 = (centers[i].z() - bottomC.z()) * 0.6; osg::ref_ptr<osg::DrawElementsUInt> de = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP); osg::Vec3d cdir(1, 0, 0); for (size_t si = 0; si < 13; ++si) { osg::Vec3d dir = rot * cdir; cdir = dir; osg::Vec3d v1 = c1 + dir * r1; osg::Vec3d v2 = c2 + dir * r2; osg::Vec3d n1 = v1 - c1; n1.normalize(); osg::Vec3d n2 = v2 - c2; n2.normalize(); float tcx = (2.0 * osg::PI * radiuses.back()) * 0.6 * (float)si / (float)12; osg::Vec2 tc1(tcx, tcy1); osg::Vec2 tc2(tcx, tcy2); de->push_back(va->size() + 0); de->push_back(va->size() + 1); va->push_back(v1); va->push_back(v2); na->push_back(n1); na->push_back(n2); ta->push_back(tc1); ta->push_back(tc2); } geom->addPrimitiveSet(de); } // 生成顶面 if (!centers.empty() && !radiuses.empty()) { const osg::Vec3d& topCenter = centers.front(); double topRadius = radiuses.front(); // 创建顶面法线(垂直向上) osg::Vec3d topNormal(0, 0, 1); // 创建内外环顶点 osg::Vec3d cdir(1, 0, 0); //osg::Quat rot(deltaAngle, osg::Vec3d(0, 0, 1)); osg::ref_ptr<osg::DrawElementsUInt> topDe = new osg::DrawElementsUInt(osg::PrimitiveSet::TRIANGLE_STRIP); for (size_t si = 0; si < 13; ++si) { // 外环顶点 osg::Vec3d outerV = topCenter + cdir * topRadius; // 内环顶点 osg::Vec3d innerV = topCenter + cdir * topHoleRadius; // 纹理坐标 float tcx = static_cast<float>(si) / 12; osg::Vec2 outerTc(tcx, 0.0f); osg::Vec2 innerTc(tcx, 1.0f); // 添加顶点 topDe->push_back(va->size()); topDe->push_back(va->size() + 1); va->push_back(outerV); va->push_back(innerV); na->push_back(topNormal); na->push_back(topNormal); ta->push_back(outerTc); ta->push_back(innerTc); cdir = rot * cdir; // 旋转到下个角度 } geom->addPrimitiveSet(topDe); } return geom.release(); }
最新发布
03-12
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值