OSG笔记:AutoTransform实现固定像素大小的图形

需求

在(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);
    }
    
  2. 第一种实现
    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;
    }
    
  3. 第二种实现
    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);
    }
    
  4. 第三种实现
    给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);
    }
    

运行截图

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值