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. 加工生产调度(prod)

    加工生产调度(prod) 题目描述 有n个部件需在A.B机器上加工,每个工件都必须经过先A后B两道工序. 已知:部件i在A.B机器上的加工时间分别为ai,bi. 问:如何安排n个工件的加工顺序,才能使 ...

  2. ftok函数的使用

    ftok函数的定义:系统建立IPC通讯 (消息队列.信号量和共享内存) 时必须指定一个ID值.通常情况下,该id值通过ftok函数得到. 头文件 #include <sys/types.h> ...

  3. CodeForces 158DIce Sculptures(枚举)

    一个暴力的枚举,枚举组成正多边形需要对应覆盖原先的几条边,范围为(1,n/3),然后维护最大值就可以了,注意初始化为-inf. #include<stdio.h> #include< ...

  4. MyBatis基础用法(一)

    <select id="getErrorTimes" resultType="Integer"> SELECT ErrorTimes FROM `e ...

  5. JQuery的方便之处——宽高设置、坐标值和滚动条+事件绑定机制

    1.元素的宽高 可以通过css来进行设置,例如:$("元素").css({"宽度":"值","高度":"值&q ...

  6. 支持持久化的内存数据库-----Redis

    一.Redis概述 1.1.什么是Redis Redis是一种高级key-value数据库.它跟memcached类似,不过数据 可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合 ...

  7. 打印等腰三角形javascript

    <html> <head> <script type="text/javascript"> var n=4;//层数 for(var i=1; ...

  8. xmlns=""

    用dom4j把两个手上的element撮合到一起,dom4j就会在被加的元素上写上xmlns="",当时我也没在意,后来用户要求去掉,查了一下还不是那么容易,原来xml本身对nam ...

  9. POJ 1015 Jury Compromise

    感觉此题略难...... 背包问题.据说有一种二维DP的写法是错的.亲测,背包做法无误. dp[i][j][k]表示前i个物品,选择j个,差值为k的情况下获得的最大总和 dp[i][j][k]=max ...

  10. CentOS6.6部署OpenStack Havana(Nova-Network版)

    CentOS6.4部署OpenStack Havana(Nova-Network版) 一 基本设备介绍 测试环境 CentOS6.4 x64 OpenStack 服务 介绍 计算 (Compute) ...