查看: 2331|回复: 5

如何控制OSG中的Geometry绘制的方块不随摄像机远近而缩放?

[复制链接]

该用户从未签到

发表于 2013-8-19 10:37:49 | 显示全部楼层 |阅读模式
据我知道有两种方法:
1. 使用一个点作为方块的中心,将其装换为屏幕坐标,然后根据屏幕坐标算出一这个点为中心的方块的四个点,再转换成OSG的world坐标,这样就实现了,但是有个问题是重载了osg::Geomtry后纹理无法加载了
2. 计算出方块在摄像机拉近或者远离时的缩放比例,动态的缩放方块,但是OSG中我不会计算缩放比例

这两种方式在OpenGL中我都实现了。

第一种实现的源码,那位帮我分析一下,纹理为什么无法加载(Geode设置纹理和Geometry设置均无效):

#include <osg/MatrixTransform>
#include <osg/ClipNode>
#include <osg/Billboard>
#include <osg/Geode>
#include <osg/Group>
#include <osg/Notify>
#include <osg/Material>
#include <osg/PolygonOffset>
#include <osg/PolygonMode>
#include <osg/LineStipple>
#include <osg/AnimationPath>
#include <osgGA/TrackballManipulator>
#include <osgDB/Registry>
#include <osgDB/ReadFile>
#include <osg/BlendFunc>
#include <osg/PointSprite>
#include <osgSim/DOFTransform>
#include <osgGA/TrackballManipulator>
#include <osgGA/FlightManipulator>
#include <osgGA/DriveManipulator>
#include <osg/Vec3d>
#include <osgViewer/Viewer>
#include <osg/ComputeBoundsVisitor>
#include <osg/Texture2D>
#include <osg/Point>
#if 1
class goSymbolPoint :
        public osg::Geometry
{
public:
        goSymbolPoint::goSymbolPoint(void);
        goSymbolPoint::goSymbolPoint( int iSize, const osg::Vec3& pos, osg::Image* pImage );
        goSymbolPoint::~goSymbolPoint(void);
        virtual void drawImplementation( osg::RenderInfo& renderInfo ) const;
        inline void SetPosition(osg::Vec3 pos){m_v3Position = pos;}
        inline void SetSize(int iS){m_iSize = iS;}
        inline void SetTexture(osg::Image* pI);
private:
        void ScreenToWorld(osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out) const;
        void WorldToScreen(osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out) const;
        void ComputeWorld(osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out) const;
        void ComputeNotVPWorld(osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out) const;

        osg::Vec3 m_v3Position, m_v3WorldPosition;
        int m_iSize;

        osg::ref_ptr<osg::Vec3Array> m_pVertexes;
        osg::ref_ptr<osg::Vec4Array> m_pColors;
        osg::ref_ptr<osg::Vec2Array> m_pTexCoord;
        osg::ref_ptr<osg::StateSet> m_pStateSet;
};

goSymbolPoint::goSymbolPoint(void)
{
        m_pStateSet = new osg::StateSet;
        m_pVertexes = new osg::Vec3Array;
        m_pColors = new osg::Vec4Array;
        m_pTexCoord = new osg::Vec2Array;
};

goSymbolPoint::goSymbolPoint( int iSize, const osg::Vec3& pos, osg::Image* pImage )
{
        m_iSize = iSize;
        m_v3Position = pos;

        m_pVertexes = new osg::Vec3Array;
        m_pColors = new osg::Vec4Array;
        m_pTexCoord = new osg::Vec2Array;

        m_pVertexes->push_back(osg::Vec3(0, 0, 0));
        m_pVertexes->push_back(osg::Vec3(10, 0, 0));
        m_pVertexes->push_back(osg::Vec3(10, 0, 10));
        m_pVertexes->push_back(osg::Vec3(0, 0, 10));

        m_pTexCoord->push_back(osg::Vec2(0, 0));
        m_pTexCoord->push_back(osg::Vec2(0, 1));
        m_pTexCoord->push_back(osg::Vec2(1, 1));
        m_pTexCoord->push_back(osg::Vec2(1, 0));

        osg::Geometry::setTexCoordArray(0, m_pTexCoord);
       

        osg::Geometry::setVertexArray(m_pVertexes);
        osg::Geometry::addPrimitiveSet(new osg:rawArrays(osg::DrawArrays:UADS, 0, 4));

        m_pColors->push_back(osg::Vec4(1, 0, 0, 1));
        osg::Geometry::setColorArray(m_pColors);
        osg::Geometry::setColorBinding(Geometry::BIND_OVERALL);

        this->setUseDisplayList(false);
};


goSymbolPoint::~goSymbolPoint(void)
{
}

void goSymbolPoint::drawImplementation( osg::RenderInfo& renderInfo ) const
{
        ((osg::Geometry*)this)->setUseDisplayList(false);
        osg::Camera* pCamera = renderInfo.getCurrentCamera();
        if(!pCamera)
        {
                ((osg::Geometry*)this)->dirtyDisplayList();
                ((osg::Geometry*)this)->dirtyBound();
                return;
        }
        int halfSize = m_iSize/2;

        osg::Vec3 v3ScreenPos, p1, p2, p3, p4, pw1, pw2, pw3, pw4, pwi1, pwi2, pwi3, pwi4, v3ComputPos;
        //ComputeWorld(pCamera, m_v3Position, v3ComputPos);
        WorldToScreen(pCamera, m_v3Position, v3ScreenPos);

        p1.set(v3ScreenPos.x() - halfSize, v3ScreenPos.y() + halfSize, 0);
        p2.set(v3ScreenPos.x() - halfSize, v3ScreenPos.y() - halfSize, 0);
        p3.set(v3ScreenPos.x() + halfSize, v3ScreenPos.y() - halfSize, 0);
        p4.set(v3ScreenPos.x() + halfSize, v3ScreenPos.y() + halfSize, 0);

        ScreenToWorld(pCamera, p1, pw1);
        ScreenToWorld(pCamera, p2, pw2);
        ScreenToWorld(pCamera, p3, pw3);
        ScreenToWorld(pCamera, p4, pw4);

        m_pVertexes->at(0).set(pw1);
        m_pVertexes->at(1).set(pw2);
        m_pVertexes->at(2).set(pw3);
        m_pVertexes->at(3).set(pw4);

        m_pTexCoord->at(0).set(0, 0);
        m_pTexCoord->at(1).set(0, 1);
        m_pTexCoord->at(2).set(1, 1);
        m_pTexCoord->at(3).set(1, 0);

        osg::Geometry::drawImplementation(renderInfo);

        /*((osg::Geometry*)this)->dirtyDisplayList();
        ((osg::Geometry*)this)->dirtyBound();*/
}

void goSymbolPoint::SetTexture( osg::Image* pI )
{
        osg::Texture2D* pTex2D = new osg::Texture2D(pI);
        m_pStateSet->setAttribute(pTex2D);
        osg::Geometry::setStateSet(m_pStateSet);
}

void goSymbolPoint::ScreenToWorld( osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out ) const
{
        osg::Matrix VPW = pCamera->getViewMatrix() *
                pCamera->getProjectionMatrix() *
                pCamera->getViewport()->computeWindowMatrix();
        osg::Matrix inverseVPW;
        inverseVPW.invert(VPW);
        v3Out = v3In * inverseVPW;
        v3Out.set(v3Out.x(), 0, v3Out.z());
}

void goSymbolPoint::WorldToScreen( osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out ) const
{

        osg::Matrix VPW = pCamera->getViewMatrix() *
                pCamera->getProjectionMatrix() *
                pCamera->getViewport()->computeWindowMatrix();

        v3Out = v3In * VPW;
        v3Out.set(v3Out.x(), v3Out.y(), 0);
}

void goSymbolPoint::ComputeWorld( osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out ) const
{
        osg::Matrix VP = pCamera->getViewMatrix() *
                pCamera->getProjectionMatrix();
        v3Out = v3In * VP;
}

void goSymbolPoint::ComputeNotVPWorld( osg::Camera* pCamera, const osg::Vec3& v3In, osg::Vec3& v3Out ) const
{
        osg::Matrix VP = pCamera->getViewMatrix() *
                pCamera->getProjectionMatrix();
        osg::Matrix InVP = osg::Matrix::inverse(VP);
        v3Out = v3In * VP;
}
#endif

osg::Geometry* GetTestPoint(osg::Vec3& pos)
{
        osg::Geometry* pGeom = new osg::Geometry;

        osg::Vec3Array* pV3Vertexes = new osg::Vec3Array;
        pV3Vertexes->push_back(pos);
        osg::Vec4Array* pV4Colors = new osg::Vec4Array;
        pV4Colors->push_back(osg::Vec4(0,0,0,1));

        pGeom->setVertexArray(pV3Vertexes);
        pGeom->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays:OINTS, 0, 1));

        pGeom->setColorArray(pV4Colors);
        pGeom->setColorBinding(osg::Geometry::BIND_OVERALL);

        osg::StateSet* pStateSet = pGeom->getOrCreateStateSet();
        osg::Point* pPA = new osg::Point;
        pPA->setSize(5);
        pStateSet->setAttributeAndModes(pPA, osg::StateAttribute::ON);

        return pGeom;
}

int main( int argc, char **argv )
{
        osgViewer::Viewer viewer;
        osg::ref_ptr<osg::Group> rootnode = new osg::Group;
        osg::ref_ptr<osg::Geode> pGeode = new osg::Geode;
       
        osg::Vec3 pos(0, 0, 0);
        rootnode->addChild(pGeode);
        osg::Image* pImage = osgDB::readImageFile("Images/maincall.png");
       
        goSymbolPoint* pSymbolPoint = new goSymbolPoint(100, pos, pImage);
        osg::ref_ptr<osg::StateSet> m_pStateSet = new osg::StateSet;
        osg::Texture2D* pTex2D = new osg::Texture2D;
        pTex2D->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D:INEAR);
        pTex2D->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::LINEAR);
        pTex2D->setDataVariance(osg::Object::DYNAMIC);
        pTex2D->setImage(pImage);
        m_pStateSet->setAssociatedTextureModes(0, pTex2D, osg::StateAttribute::ON);
        pGeode->setStateSet(m_pStateSet);

        pGeode->addDrawable(pSymbolPoint);
        osg::Geometry* pPointTest = GetTestPoint(pos);
        pGeode->addDrawable(pPointTest);

        viewer.setSceneData(rootnode);
        viewer.setCameraManipulator(new osgGA::TrackballManipulator);
        viewer.setUpViewInWindow(20, 100, 800, 600);
        viewer.setLightingMode(osg::View::NO_LIGHT);
        return viewer.run();
}

该用户从未签到

发表于 2013-8-19 10:57:14 | 显示全部楼层
autotransfor

该用户从未签到

发表于 2013-8-19 12:01:25 | 显示全部楼层
原理就是实时计算跟视点的位置 和 大小

该用户从未签到

 楼主| 发表于 2013-8-19 12:53:54 | 显示全部楼层
fenma3422 发表于 2013-8-19 10:57
autotransfor

AutoTransform 有些作用但是图形的位置固定不变了也,应该是图形的位置是随着缩放改变的,图形的大小不变,就像PointSprint的效果,但是PointSprint不能使用一个PointSprint的一个纹理,如果是一个PointSprint的一个纹理话,PointSprint就显示不出来了。

该用户从未签到

 楼主| 发表于 2013-8-19 12:55:12 | 显示全部楼层
liuzhiyu123 发表于 2013-8-19 12:01
原理就是实时计算跟视点的位置 和 大小

怎么计算呢?

该用户从未签到

 楼主| 发表于 2013-8-19 14:45:36 | 显示全部楼层
问题解决了,用错函数了,应该用StateSet::setTextureAttributeAndModes设置纹理
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表