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. Javascript面向对象编程(二):构造函数的继承

    这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个" ...

  2. activemq学习

    一.特性及优势 1.实现JMS1.1规范,支持J2EE1.4以上2.可运行于任何jvm和大部分web容器(ActiveMQ works great in any JVM)3.支持多种语言客户端(jav ...

  3. linux下libreoffice安装测试

    一.Linux安装 wget http://download.documentfoundation.org/libreoffice/stable/4.4.6/rpm/x86_64/LibreOffic ...

  4. C#排列组合类

    //----------------------------------------------------------------------------- // // 算法:排列组合类 // // ...

  5. 用JavaScript 来将数字转换成字符。

    背景: 一切嵌入式设备上面的信息,比如设备名称,设备时区是可以写入到设备上面的寄存器中的(一个寄存器两个字节,2*8 bit),比如 -1 ,写入到寄存器中为 2d31,然后可以通过一些进程将寄存器中 ...

  6. ViewController加载顺序与self.view

    转载自:http://blog.csdn.net/ishaoc/article/details/42172749   ViewController的加载顺序如下   从Stroyboard和xib中加 ...

  7. Python3基础 list() 将一个元组转换成列表

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  8. Super Jumping! Jumping! Jumping! 基础DP

    Super Jumping! Jumping! Jumping! Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 ...

  9. 转 linux目录介绍

    以下用一个表格来罗列linux默认的目录或文件及其用途: 目录/文件 用途 来源 / /处于Linux文件系统树形结构的最顶端,它是Linux文件系统的入口,所有的目录.文件.设备都在/之下. - / ...

  10. 网页被卷去的高: document.body.scrollTop;

    网页可见区域宽: document.body.clientWidth;网页可见区域高: document.body.clientHeight;网页可见区域宽: document.body.offset ...