OSG笔记:AutoTransform实现固定像素大小的图形
  WtpFkP2ympcR 2023年11月02日 46 0


需求

在(200,0,0)位置绘制固定10像素大小的正方体

实现方式

  1. 为了便于观察,例子中绘制了两条直线,相交于(200,0,0)。
//两根直线交于(200, 0, 0),用于辅助观察
{
	osg::Geometry* pLineGeom = new osg::Geometry();
	osg::Vec3Array* pVertexArray = new osg::Vec3Array();
	pVertexArray->push_back(osg::Vec3(-400, 0, 0));
	pVertexArray->push_back(osg::Vec3(400, 0, 0));

	pVertexArray->push_back(osg::Vec3(200, 0, 400));
	pVertexArray->push_back(osg::Vec3(200, 0, -400));

	pLineGeom->setVertexArray(pVertexArray);
	pLineGeom->addPrimitiveSet(
		new osg::DrawArrays(osg::DrawArrays::LINES, 0, pVertexArray->size()));
	osg::Geode* pShapeGeode = new osg::Geode();
	pShapeGeode->addDrawable(pLineGeom);
	pRoot->addChild(pShapeGeode);
}
  1. 第一种实现
    osg::Box的中心点直接设置为(200,0,0),测试发现,这是不正确的实现。
{
	osg::AutoTransform* pAt = new osg::AutoTransform();
	pAt->setAutoScaleToScreen(true);
	pRoot->addChild(pAt);

	osg::ShapeDrawable* pShape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(200, 0, 0), 20));
	pShape->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
	osg::Geode* pShapeGeode = new osg::Geode();
	pShapeGeode->addDrawable(pShape);
	pAt->addChild(pShapeGeode);
}

不正确的原因分析:
AutoTransform实现固定像素大小的原理,就是计算当前视图下的缩放因子让图形保持固定大小。

参看AutoTransform计算自身节点矩阵的函数AutoTransform::computeMatrix(),以及
计算到世界坐标系的函数AutoTransform::computeLocalToWorldMatrix可知(注:源码在后文中有列出),计算Box中心点的最终坐标公式如下:

Box中心点 * (pivot矩阵缩放矩阵旋转矩阵*位置矩阵 * 父节点矩阵)

当前例子下,pivot矩阵、旋转矩阵均为单位矩阵,所以问题简化为

Box中心点 * (缩放矩阵 * 位置矩阵 * 父节点矩阵)

因为最先应用的是缩放矩阵,如当前视图下,缩放因子为2.0,则Box中心点*缩放矩阵后的坐标点为(400,0,0),不满足需求。

void AutoTransform::computeMatrix() const
{
    if (!_matrixDirty) return;
    
    _cachedMatrix.makeRotate(_rotation);
    _cachedMatrix.postMultTranslate(_position);
    _cachedMatrix.preMultScale(_scale);
    _cachedMatrix.preMultTranslate(-_pivotPoint);
    
    _matrixDirty = false;
}

bool AutoTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
    if (_matrixDirty) computeMatrix();
    
    if (_referenceFrame==RELATIVE_RF)
    {
        matrix.preMult(_cachedMatrix);
    }
    else // absolute
    {
        matrix = _cachedMatrix;
    }
    return true;
}
  1. 第二种实现
    osg::AutoTransform节点位置坐标设置为(200,0,0),此方法正确的原因可参看第一种实现原因分析
{
	osg::AutoTransform* pAt = new osg::AutoTransform();
	pAt->setAutoScaleToScreen(true);
	pAt->setPosition(osg::Vec3(200, 0, 0));
	pRoot->addChild(pAt);

	osg::ShapeDrawable* pShape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 20));
	pShape->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
	osg::Geode* pShapeGeode = new osg::Geode();
	pShapeGeode->addDrawable(pShape);
	pAt->addChild(pShapeGeode);
}
  1. 第三种实现
    给osg::AutoTransform节点增加个父节点(矩阵节点),让后设置父节点的位置为(200,0,0),此方法正确的原因可参看第一种实现原因分析
{
	osg::PositionAttitudeTransform* pParentNode = new osg::PositionAttitudeTransform();
	pParentNode->setPosition(osg::Vec3(200, 0, 0));
	pRoot->addChild(pParentNode);

	osg::AutoTransform* pAt = new osg::AutoTransform();
	pAt->setAutoScaleToScreen(true);
	pParentNode->addChild(pAt);

	osg::ShapeDrawable* pShape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(0, 0, 0), 20));
	pShape->setColor(osg::Vec4(1.0, 0.0, 0.0, 1.0));
	osg::Geode* pShapeGeode = new osg::Geode();
	pShapeGeode->addDrawable(pShape);
	pAt->addChild(pShapeGeode);
}

运行截图

OSG笔记:AutoTransform实现固定像素大小的图形_旋转矩阵


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  lG7RE7vNF4mc   2023年11月02日   32   0   0 好用贴图缩放
  QmTRttZdoSM7   2023年11月02日   42   0   0 数据idelinux缩放
  fFNahfJvxgqO   2023年11月02日   39   0   0 快捷键右键gimp缩放
  lG7RE7vNF4mc   2023年11月13日   24   0   0 好用贴图缩放
WtpFkP2ympcR