OSG世界坐标转屏幕坐标

#define M(row,col) m[col * 4 + row]

void Transform_Point(double out[4], const double m[16], const double in[4]){
    out[0] = M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
    out[1] = M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
    out[2] = M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
    out[3] = M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
}

osg::Vec3d WorldToScreen(osgViewer::View* view,osg::Vec3 worldpoint){
    double in[4], out[4];

in[0] = worldpoint._v[0];
    in[1] = worldpoint._v[1];
    in[2] = worldpoint._v[2];
    in[3] = 1.0;
    //获得当前的投影矩阵和模型视图矩阵

osg::Matrix projectMatrix= view->getCamera()->getProjectionMatrix();
    osg::Matrix viewprojectMatrix = view->getCamera()->getViewMatrix();
    //下面计算 模型视图矩阵 * 投影矩阵 * 视口窗口变换矩阵
    double modelViewMatrix[16];
    memcpy(modelViewMatrix,viewprojectMatrix.ptr(),sizeof(GLdouble) * 16);
    Transform_Point(out, modelViewMatrix, in);

double myprojectMatrix[16];
    memcpy(myprojectMatrix,projectMatrix.ptr(),sizeof(GLdouble) * 16);

Transform_Point(in, myprojectMatrix, out);

if(int(in[3] * 100000) == 0){
       return osg::Vec3d(0,0,0);
    }

in[0] /= in[3];
    in[1] /= in[3];
    in[2] /= in[3];

int viewPort[4];
    osg::Viewport* myviewPort = view->getCamera()->getViewport();
    viewPort[0] = 0;
    viewPort[1] = 0;
    viewPort[2] = mConfigure->GetScreenWidthPixel(); //横向象素点
     viewPort[3] = mConfigure->GetScreenHeightPixel();//纵向象素点
    //计算 三维点在屏幕上的二维投影点
    osg::Vec3d sceenPoint;
    sceenPoint._v[0] = (int)(viewPort[0] + (1 + in[0]) * viewPort[2] / 2 + 0.5);
    sceenPoint._v[1] = (int)(viewPort[1] + (1 + in[1]) * viewPort[3] / 2 + 0.5);
    sceenPoint._v[2] = 0;
    return sceenPoint;
}

 
 
一颗场景树,远不止只有叶子节点Geode 因此.在osg中有着一些各种各样的组节点.osg::Group.还有许多从osg::Group 继承的其他各种各样的组节点.类太多了.附类继承图地址

我目前只是尝试使用了MatrixTransform PositionAttitudeTransform Group Projection Switch 等各种功能的组节点.  在介绍MatrixTransform 和 PositionAttitudeTransform 节点前.我想先介绍下osg当中矩阵的一些相关知识.

其实,无需关心osg矩阵是如何实现的.但是要记住的是osg中采用的左乘操作,我们平时里讨论的操作如旋转平移等.
      OpenGL的:    newpos = R* T * oldpos    //先执行平移 后执行 旋转 (全局坐标系)
      osg当中:  newpos  =oldpos * T *R    //先执行平移 后执行旋转    (全局坐标系)
因为在osg当中矩阵执行的操作则是行矩阵操作.因此为了跟OpenGL的列矩阵做同步 而不在定义的时候就相当于做了一个转置操作.即
 

因此在osg/State 中 在使用applyModelViewMatrix()   osg/State 是OpenGL状态机的封装.是与OpenGL交互的类

inline void applyModelViewMatrix(const osg::RefMatrix* matrix)
        {
            if (_modelView!=matrix)
            {
                if (matrix)
                {
                    _modelView=matrix;
                    glLoadMatrix(matrix->ptr());
                }
                else
                {
                    _modelView=_identity;
                    glLoadIdentity();
                }
            }
        }

它是直接使用glLoadMatrix(matrix)进行载入矩阵的.因此它的转置刚好适应了OpenGL列优先的模式.

你只需牢记 在OSG当中变换的步骤则是左乘操作(全局坐标系)..即左边的是先执行变换的.

谈完如上的那些之后.我们现在来看MatrixTransform 和PositionAttitudeTransform.

参考坐标系有三种
            RELATIVE_RF,    //全局 相对 ()
            ABSOLUTE_RF,  //局部  绝对 ()
            ABSOLUTE_RF_INHERIT_VIEWPOINT   //基于视点一个局部坐标系.很少用到.

MatrixTransform 故名 矩阵变换节点.在位于它的节点之下的节点都将按照这它的矩阵变换来进行模型变换操作.因此 MatrixTransform的主要功能之一就是提供模型变换操作..你只要根据你所需要的设置其模型矩阵就行.
即执行 setMatrix() 因此.查看计算当前World矩阵的方法就可以很清晰的明白其最后结果就是:

如果是相对的.那么 先执行自身的变换,在执行父节点的变换操作.这类似OpenGL中后写的变换是先执行的一样(全局坐标系考虑)
否则是绝对的,那么当前矩阵就是自身矩阵

bool MatrixTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
    if (_referenceFrame==RELATIVE_RF)
    {
        matrix.preMult(_matrix);
    }
    else // absolute
    {
        matrix = _matrix;
    }
    return true;
}

PositionAttibuteTransform 就是位置姿态节点..即我们只可以调整该节点的所有孩子的位置以及姿态.,我们也先来看一下它的矩阵变换:

bool PositionAttitudeTransform::computeLocalToWorldMatrix(Matrix& matrix,NodeVisitor*) const
{
    if (_referenceFrame==RELATIVE_RF)
    {
        matrix.preMultTranslate(_position);
        matrix.preMultRotate(_attitude);
        matrix.preMultScale(_scale);
        matrix.preMultTranslate(-_pivotPoint);
    }
    else // absolute
    {
        matrix.makeRotate(_attitude);
        matrix.postMultTranslate(_position);
        matrix.preMultScale(_scale);
        matrix.preMultTranslate(-_pivotPoint);
    }
    return true;
}

PositionAttibuteTransform 的矩阵变换顺序的固定的.可以说是MatrixTransform的一个特例.,操作顺序我就不在详谈了.因为它的功能就是为了实现姿态和位置.还有缩放等.
因此 setPivotPoint 将使得之后的变换将会基于此平移操作执行.

那么实现一个例子来观察他们的效果: 下面的例子则是
<1> 使用PositionAttitudeTransform 设置左边的牛. 位置位于(-10,0,0) 姿态为绕z轴旋转90度.
<2> 使用MatrixTransform 设置右边的牛,  先执行平移操作(10,0,0) 在绕z轴旋转60度 因此使得这只牛偏屏幕内部一点.(你画个坐标轴 按全局思路演示 则就知道牛在上面位置了.!)

osg::Node* createTrans()
{
    /** declare a root node*/
    osg::Group* root = new osg::Group;
    /** declare a Position Node*/
    osg::PositionAttitudeTransform* posCow = new osg::PositionAttitudeTransform;
    root->addChild(posCow);
    /** declare a Matrix Node*/
    osg::MatrixTransform* matrixCow  = new osg::MatrixTransform;
    root->addChild(matrixCow);

    osg::Node* cow = osgDB::readNodeFile("cow.osg");

    /**
        When use Position Node and the ReferenceFrame is RELATIVE_RF
        the matrix is Compute  Trans(-pivot) * scale * Rotate * Trans(Pos)
        here the pivot and scale is default,so it means that make rotate firstly.
    */
    posCow->addChild(cow);
    osg::Quat quat;
    quat.makeRotate(osg::PI_2,osg::Vec3(0.0,0.0,1.0));
    posCow->setAttitude(quat);
    posCow->setPosition(osg::Vec3(-,0.0,0.0));

    /**
        when use Matrix Node  you can set the matrix what you want.
        here , it  make trans firstly and then make rotate.
    */
    matrixCow->addChild(cow);
    quat.makeRotate(osg::DegreesToRadians(60.0),osg::Vec3(0.0,0.0,1.0));
    matrixCow->setMatrix(osg::Matrixd::translate(osg::Vec3(10.0,0.0,0.0))*osg::Matrixd::rotate(quat));

    return root;
}
 

OSG世界坐标转屏幕坐标(转载)的更多相关文章

  1. Unity 坐标 转换 详解 World世界坐标 Screen屏幕坐标 View视口坐标 GUI坐标 NGUI坐标 localPosition相对父级坐标

    在制作游戏中我们经常会遇到这样一个需求: 在人物模型的上面显示 名字.称号 一类的文字或者图片 如下图 人物模型属于是Camera1   UI Title信息属于NGUI Camera2 如下图 这时 ...

  2. threejs 世界坐标与屏幕坐标相互转换

    屏幕坐标转世界坐标: let pX = (screenPoint.x / this.scene.renderer.domElement.clientWidth) * 2 - 1; let pY = - ...

  3. Layabox 世界坐标和屏幕坐标互转

    最近在入坑Layabox,花了几天时间做世界坐标和屏幕坐标的互转,由于Layabox没有现成的代码所以只能自己手动写,大概就是模仿unity里面的ScreenToWorldPoint和WorldToS ...

  4. OSG开发概览(转载)

    OSG开发概览 1 OSG基础知识 Ø OSG是Open Scene Graphic 的缩写,OSG于1997年诞生于以为滑翔机爱好者之手,Don burns  为了对滑翔机的飞行进行模拟,对open ...

  5. ogre世界坐标鱼屏幕坐标相互转换

    bool worldCoordToScreen(Vector3 objPos, Camera* cam, Vector2 screenRect,  Vector2& screenPos) { ...

  6. threejs 世界坐标转化为屏幕坐标

    网站: http://www.yanhuangxueyuan.com/Three.js_course/screen.html 方法.project 通过Vector3对象的方法project,方法的参 ...

  7. u3d 楼梯,圆环,椭圆,直线运动。世界坐标。点击。U3d stair, ring, ellipse, linear motion.World coordinates.Click .

    u3d 楼梯,圆环,椭圆,直线运动.世界坐标.点击. U3d stair, ring, ellipse, linear motion.World coordinates.Click . 作者:韩梦飞沙 ...

  8. 【浅墨Unity3D Shader编程】之一 夏威夷篇:游戏场景的创建 & 第一个Shader的书写

    本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接:http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅墨)  ...

  9. NGUI系列教程五(角色信息跟随)

    在一些网络游戏中,我们常常可以看到角色的上方显示着角色的名称,等级,血量等信息.它们可以跟随角色移动,并且可以显示和隐藏.今天我们就来学习一下这些功能的实现方法.1. 新建unity工 程,导入NGU ...

随机推荐

  1. Linux 查询程序安装路径 是否安装

    rpm -ql httpd #[搜索rpm包]--list所有文件安装目录 rpm -q mysql  //查询程序是否安装 关于rpm详细用法 参考 http://www.cnblogs.com/x ...

  2. Why attitude is more important than IQ

    原文:http://www.businessinsider.com/why-attitude-is-more-important-than-iq-2015-9?IR=T& LinkedIn I ...

  3. s-palindrome

    s-palindrome Let's call a string "s-palindrome" if it is symmetric about the middle of the ...

  4. gridview如何隐藏一列数据,但又可以使用这列数据

    解决方案在RowCreated事件中书写如下代码 void GridView1_RowCreated(object sender, GridViewRowEventArgs e)    {       ...

  5. 1317: Square(DFS+剪枝)

    Description Given a set of sticks of various lengths, is it possible to join them end-to-end to form ...

  6. Byte数组和Int的互相转换

    public static int bytesToInt(byte[] bytes) { int addr = bytes[0] & 0xFF; addr |= ((bytes[1] < ...

  7. linux安装安卓开发工具android studio

    http://www.android-studio.org/ http://android-studio.org/index.php/docs/guide 最近要接触android编程,本来想装ecl ...

  8. 简单三段式状态机实验1-SOS

    一直想从一段式状态机切换到三段式状态机,从书上和网上不断搜寻三段式案例及方法,感觉很简单,就想拿之前做过的实验把一段式改成三段式,可是写起来并非那么简单,很棘手,改完后也没有成功,尤其状态机里面的计数 ...

  9. android4.0 的图库Gallery2代码分析(三) 之Applition的初始化准备

    Applition的初始化准备 图库的一切动作都明显地起源于Application.这是区别与其他那种感觉不到Application存在,仅仅感觉到Activity存在的简单应用的一个特点. 图库的a ...

  10. Python+Selenium WebDriver API:浏览器及元素的常用函数及变量整理总结

    由于网页自动化要操作浏览器以及浏览器页面元素,这里笔者就将浏览器及页面元素常用的函数及变量整理总结一下,以供读者在编写网页自动化测试时查阅. from selenium import webdrive ...